1、继承:
通过继承定义一个类,它们的类型之间的关系建模,共享共有的东西,实现各自本质不同的东西。
C++的“继承”特性可以提高程序的可复用性。
继承定义格式:
2、类的大小:
class Base
{
public:
Base(int data)
{
cout << data << endl;
cout << "Base()" << this << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
//求类大小时,只求数据成员的大小三个int类型的数据成员,所以大小为12
class Base1
{
public:
Base1(int data)
{
cout << "Base1()" << endl;
}
~Base1()
{
cout << "~Base1()" << endl;
}
};
//当类没有数据成员时,通常系统都会给一个值为1的空间,因为类的大小不可能为0,但是系统又要给类分配空间,为了节省空间,会分配最小空间
class Test
{
public:
Test(int data)
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
class Derive :public Base, public Base1
{
public:
Derive()
:d(10)
, Base1(10)
, Base(20)
{
cout << "Derive()" << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
int _pri;
Test d;
};
int main()
{
cout << sizeof(Base) << endl; //12
cout << sizeof(Base1) << endl; //1
cout << sizeof(Derive) << endl; //32
system("pause");
return 0;
}
3、类的访问:
class Base
{
public:
Base(int data)
{
cout << data << endl;
cout << "Base()" << this << endl;
}
void Show()
{
cout << "Base::Show()" << endl;
cout << "_pri=" << _pri << endl;
cout << "_pro=" << _pro << endl;
cout << "_pub=" << _pub << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
class Base1
{
public:
Base1(int data)
{
cout << "Base1()" << endl;
}
~Base1()
{
cout << "~Base1()" << endl;
}
};
class Test
{
public:
Test(int data)
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
class Derive :public Base, public Base1
{
public:
Derive()
:d(10)
, Base1(10)
, Base(20)
{
cout << "Derive()" << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
void Display()
{
cout << "_pri=" << _pri << endl;
cout << "_pro=" <<& _pro << endl;
cout << "-pub=" << &_pub << endl;
cout << "_dPri=" << &_dPri << endl;
cout << "_dPro=" << &_dPro << endl;
cout << "_dPub=" << &_dPub << endl;
}
void Show()
{
_pri = 10;
//Base::_pri = 10;
//私有成员只能在基类访问,在派生类和其他地方都不能访问
cout << "Derive::Show()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
int _pri;
Test d;
};
int main()
{
cout << sizeof(Base) << endl; //12
cout << sizeof(Base1) << endl; //1
cout << sizeof(Derive) << endl; //32
Derive d;
//调用构造函数时,先进Base类调用构造函数初始化Base,再进Base1初始化Base1
//最后再进Test类初始化对象d,因为d是在派生类中创建的,所以要最后初始化,
//Base和Base1初始化顺序按照继承顺序执行,并不按照派生类中初始化列表中的顺序进行
d.Show();
//调用派生类中的函数Show(),在函数中_pri(派生类中的公有成员_pri)被赋值为10,
//子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问
d.Base::Show();
//调用基类Base中的Show(),因为都未赋值,所以显示的都为随机值
d.Display();
//_pri(派生类中的)显示为10,其他显示的地址,都相差4字节,说明在类中,开辟的地址是连续的
d._dPub = 10;
d.Show();
//d._dPro = 20; //保护成员在类外不可以访问
system("pause");
return 0;
}
运行结果:(运行环境是VS2013)
总结:
1、基类的private成员在派生类中是不能被访问的。 2、如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。保护成员限定符是因继承才出现的。 3、public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。 4、protetced/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,是 has-a 的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。 5、不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能访问)。 6、使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。 7、在实际运用中一般使用都是public继承,极少场景下才会使用protetced/private继承. 1、私有成员只能在基类访问,在派生类和其他地方都不能访问 2、保护成员在类外不可以访问 3、在派生类中初始化基类时,系统会按照继承的先后顺序依次调用相应的构造函数来初始化,而不是根据初始化列表中的顺序 1、在继承体系中基类和派生类是两个不同作用域。 2、子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏 --重定义 3、注意在实际中在继承体系里面最好不要定义同名的成员。 |
【继承关系中构造函数调用顺序】
【说明】
1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
class Base
{
public:
Base(int data)
{ }
};
class Base1
{
public:
Base1(int data)
{ }
};
class Derive: public Base, public Base1
{
public:
Derive()
: Base1(10)
, Base(20)
{ }
};
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。
【继承关系中析构函数调用顺序】
4、友元与继承及其赋值兼容:
class Base
{
public:
friend void Display(Base b);
Base(int data)
{
cout << data << endl;
cout << "Base()" << this << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
class Derive :public Base
{
public:
friend void Display(Base b);
Derive()
:Base(20)
{
cout << "Derive()" << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
int _pri;
//子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问
};
void Display(Base b)
{
cout << b._pri << endl;
cout << b._pro << endl;
cout << b._pub << endl;
Derive d;
//cout << d._dPri << endl;
//友元关系不能继承,基类友元不能访问子类私有和保护成员
//如果Display是基类Base的友元函数,则不能访问派生类的私有和保护成员
//如果Display是派生类的友元函数,则可以访问
}
int main()
{
Derive d; //子类对象
Base b(0); //父类对象
b = d; //子类对象可以赋值给父类对象
//d = b; //父类对象不可以赋值给子类对象
Base*pBase = &d; //父类指针
Derive *pd = (Derive*)&b; //子类指针
pBase = pd; //父类的指针/引用可以指向子类对象
//pd = pBase; //子类的指针/引用不能指向父类对象 (可以通过强制类型转换实现)
return 0;
}
系统给出的错误提示:
总结:
1、友元关系不能继承,基类友元不能访问子类私有和保护成员
2、子类对象可以赋值给父类对象
3、父类对象不可以赋值给子类对象
4、父类的指针/引用可以指向子类对象
5、子类的指针/引用不能指向父类对象 (可以通过强制类型转换实现)
6、基类定义了static成员,则整个继承体系里面只有一个这样的成员。
除了单继承,还有多继承和菱形继承,以下可区别它们之间的区别:
转载于:https://blog.51cto.com/10921020/1762068