C++子类父类构造函数的关系
三种继承关系:https://blog.csdn.net/yuchenshu89757/article/details/52262737
c++默认是private继承,子类继承时要加public
构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造方法。
如果没有显式的构造函数,编译器会给一个默认的构造函数,并且该默认的构造函数仅仅在没有显式地声明构造函数情况下创建。
构造原则如下:
1. 如果子类没有定义构造方法,则调用父类的无参数的构造方法。
2. 如果子类定义了构造方法,不论是无参数还是带参数,在创建子类的对象的时候,首先执行父类无参数的构造方法,然后执行自己的构造方法。
3. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数,则会调用父类的默认无参构造函数。
4. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类自己提供了无参构造函数,则会调用父类自己的无参构造函数。
5. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类只定义了自己的有参构造函数,则会出错(如果父类只有有参数的构造方法,则子类必须显示调用此带参构造方法)。
6. 如果子类调用父类带参数的构造方法,需要用初始化父类成员对象的方式,比如:
#include <iostream.h> class animal { public: animal(int height, int weight) { cout<<"animal construct"<<endl; } … }; class fish:public animal { public: fish():animal(400,300) { cout<<"fish construct"<<endl; } … }; void main() { fish fh; }
在fish类的构造函数后,加一个冒号(:),然后加上父类的带参数的构造函数。这样,在子类的构造函数被调用时,系统就会去调用父类的带参数的构造函数去构造对象。这种初始化方式,还常用来对类中的常量(const)成员进行初始化,如下面的代码所示:
class point
{
public:
point():x(0),y(0)
private:
const int x;
const int y;
};
继承:
在没有继承的情况下,protected跟private相同。在派生类的时候才出现分化。
上面那段英文前两条都很好理解,基类对象不能访问基类的protected成员,派生类中可以访问基类的protected成员。也就是说private成员是不能被继承的,只有public,protected的成员才可以被继承。
就是最后一条有些迷惑人,派生类对象如果要访问基类protected成员只有通过派生类对象,派生类不能访问基类对象的protected成员。
请注意 drived class和drived object:派生类和派生类对象。第一点和第二点都是针对派生类来说的。
对于第三点总结一句话:只有在派生类中才可以通过派生类对象访问基类的protected成员。
#include <iostream> using namespace std; class Base { public: Base(){}; virtual ~Base(){}; protected: int int_pro; }; class A : public Base { public: A(){}; A(int da){int_pro = da;} void Print(A &obj){obj.int_pro = 24;} void PrintPro(){cout << "The proteted data is " << int_pro <<endl;} }; int main() { A aObj; A aObj2(5); aObj2.PrintPro(); aObj.Print(aObj2); aObj2.PrintPro(); //注释1 //aObj.int_pro = 8; }
编译运行结果如下:
The protected data is 5
The protected data is 24
可见,在派生类内部直接访问protected成员和访问派生类对象基类的protected成员都是可行的。
但是若果解开注释1.就会编译报错。
很多书上都说有派生类的情况下protected的访问权限同public。这种说法是不对的,类内部直接访问没什么区别,但是访问对象基类的protected成员只能是在该类的内部。
我这里只列举了只有一层继承的情况,如果有多重继承的情况,比如三层。那么。中间层的类的内部还可以访问第三层类对象的基类成员,但是不能访问第三层类自己的protected的成员。
继承时子类的会隐藏父类的同名成员函数,即使子类成员和基类成员的形参列表不一致。
struct B{ int m(); }; struct D:B{ //struct默认是public继承 int m(int); //隐藏了基类的m }; D d; B b; b.m(); //调用B::m d.m(10); //调用D::m d.m(); //错误,基类的m被隐藏了 d.B::m(); //正确所以基类与子类中的虚函数必须有相同的形参列表。