C++作为介于C和Java之间的语言,不仅可以使用C语言中高效的指针,而且继承了Java中面向对象的编程思想。 它在去年的编程语言排行榜上首次超越Java,进入前三名。
今天的文章将讲解C++中的面向对象编程思想。 说到面向对象编程,就不得不说到对象的三大特性:封装性、继承性和多态性。 本文将重点讨论这三个特征。
目录封装
封装是面向对象编程的三大特征之一。
核心理念一:用属性和行为作为一个整体来表达生活中的事物。
class People {
public:
string name;
void eat();
private:
string sex;
};
注:类中的属性和行为统称为成员属性,成员称为成员变量,行为成员称为成员函数。
核心思想2:对属性和行为进行权限控制
面向对象编程的权限包括:
一般包装原则:
对所有成员变量使用权限,并使用成员函数set和get读写成员变量,防止成员变量暴露给外界。
继承
继承是面向对象编程过程中一个非常重要的特性。 它允许开发者保存原有类的特性并扩展流程、添加功能等。新继承的类称为派生类(Java中习惯上称其为子类),继承的类称为派生类。基类(Java中习惯上称其为父类)。
对于有Java基础的同学来说是非常熟悉的,所以对于开发者来说,上手C++会比其他程序员更快。 虽然字面意思差不多,但是C++继承和Java还是有很多区别的。 下面小宇就一一来了。
继承格式
class 派生类名:继承方式 基类的名称
class A :public B
继承基本代码:
class Father {
public:
string name = "father";
int age = 45;
};
class Son :public Father {
public:
string sex = "male";
void print() {
cout << "name:" << name << " age:" << age << " sex:" << sex << endl;
}
};
void extendsTest::mainTest()
{
Son son;
son.print();
};
打印结果:
name:father age:45 sex:male
基类中的name和age是子类和父类共享的成员变量。 每个人都有名字和年龄。 虽然子类中没有定义,但是可以从父类继承。 这就是继承的意义。
sex 属性是 Son 子类中唯一的成员变量。 可以修改父类特有的元素,以表明该元素为当前父类所有,不能被子类获取。 每个人都明白这一点。
这里想说一下子类定义继承过程中父类的继承方法:如下:
class Son :public Father
类成员/继承方法继承继承
父类成员
子类成员
子类成员
子类成员
父类成员
子类成员
子类成员
子类成员
父类成员
子类不可见
子类不可见
子类不可见
权限记住规则:
子类的权限受到父类的权限和子类的继承方法的限制。 子类从父类的继承方法只是重新封装了父类的成员。 在大多数情况下,继承就足够了。 除非你不希望其他类引用该类的父类元素。
子类与父类具有相同的属性或方法
假设子类有一个与父类同名的元素,那么会优先使用子类的元素。
class Father {
public:
string name = "father";
int age = 45;
};
class Son :public Father {
public:
string sex = "male";
string name = "son";
void print() {
cout << "name:" << name << " age:" << age << " sex:" << sex << endl;
}
};
void extendsTest::mainTest()
{
Son son;
son.print();
};
打印结果:
name:son age:45 sex:male
如果这时候必须访问父类的元素怎么办? 只需添加父类修饰符即可。
void print() {
cout << "name:" << Father::name << " age:" << age << " sex:" << sex << endl;
}
那么同名方法呢?这就涉及到面向对象编程中的函数重载和多态问题,后面会解释。
单继承和多重继承
C++ 中的继承与 Java 中的继承不同,Java 中只能从一个父类继承。 在C++中,可以继承多个父类,因此单继承和多重继承是有区别的:
单一继承
只有一个父类
class A:public B{
}
多重继承
有多个父类
class A:public B,public C {
}
钻石传承
钻石继承图:
钻石继承有哪些问题?
class A {
public:
string name;
};
class B :public A {
public:
int age;
};
class C :public A {
public:
string sex;
};
class D :public B, public C {
public:
int id;
};
int main()
{
D student;
student.name = "小明";
student.age = 18;
student.sex = "男";
student.id = 666;
return 0;
}
问题就出现了:
原因是B和C同时继承了A,所以B和C同时拥有name属性。 如果直接使用.name,编译器无法确定属于哪个类名。 针对这种情况,有以下几种解决方案:
student.B::name = "小明";
class B :virtual public A {
public:
int age;
};
class C :virtual public A {
public:
string sex;
};
多重继承是C++复杂性的体现。 有了多重继承,就有了钻石继承。 为了解决菱形继承问题,出现了菱形虚拟继承,其底层实现非常复杂。 因此,一般不建议设计多重继承,更不能设计菱形继承。