Derived classes
派生类
任何类类型%28是否用类键声明class
或struct
%5月29日宣布为导出
从一个或多个基类
它们反过来也可以从它们自己的基类
派生,从而形成继承层次结构。
类的基类子句中提供了基类列表。类声明语法基子句由字符组成。:
后面是一个或多个基说明符的逗号分隔列表。
attr(optional) access-specifier(optional) virtual-specifier(optional) class-or-decltype | | |
---|
attr(C++11) | - | optional sequence of any number of attributes |
---|---|---|
access-specifier | - | one of private, public, or protected |
virtual-specifier | - | the keyword virtual |
虚拟说明符和访问说明符可能以任何顺序出现.
base-specifiers in a base-clause may be pack expansions. A class or struct declared final cannot appear in base-clause. | (since C++11) |
---|
如果省略了访问说明符,则默认为public
用于用类键声明的类。struct
和private
用于用类键声明的类。class
...
二次
struct Base {
int a, b, c;
};
// every object of type Derived includes Base as a subobject
struct Derived : Base {
int b;
};
// every object of type Derived2 includes Derived and Base as subobjects
struct Derived2 : Derived {
int c;
};
二次
基子句中列出的类是直接基类。他们的基础是间接基类。不能多次将同一个类指定为直接基类,但同一个类可以是直接基类,也可以是间接基类。
每个直接和间接基类都存在,如基类子对象
,在实现自定义偏移量的派生类的对象表示中。空基类通常不会增加派生对象的大小,原因是空基优化基类次bobject的构造函数由派生类的构造函数调用:参数可以提供给成员初始化列表...
虚拟基类
对于指定的每个不同的基类virtual
,大多数派生对象仅包含该类型的一个基类子对象,即使该类多次出现在继承层次结构%28中,只要它是继承的。virtual
每次%29。
二次
struct B { int n; };
class X : public virtual B {};
class Y : virtual public B {};
class Z : public B {};
// every object of type AA has one X, one Y, one Z, and two B's:
// one that is the base of Z and one that is shared by X and Y
struct AA : X, Y, Z {
void f() {
X::n = 1; // modifies the virtual B subobject's member
Y::n = 2; // modifies the same virtual B subobject's member
Z::n = 3; // modifies the non-virtual B subobject's member
std::cout << X::n << Y::n << Z::n << '\n'; // prints 223
}
};
二次
具有虚拟基类的继承层次结构的一个示例是标准库的ioStreams层次结构:std::istream
和std::ostream
派生自std::ios
使用虚拟继承。std::iostream
都是从std::istream
和std::ostream
的每一个例子std::iostream
包含std::ostream
次弹射std::istream
一次弹出,只有一次std::ios
次目标%28,因此,只有一个std::ios_base
29%。
所有虚拟基子对象都在任何非虚拟基子对象之前初始化,因此只有大多数派生类调用其中虚拟基的构造函数。成员初始化列表*
二次
struct B {
int n;
B(int x) : n(x) {}
};
struct X : virtual B { X() : B(1) {} };
struct Y : virtual B { Y() : B(2) {} };
struct AA : X, Y { AA() : B(3), X(), Y() {} };
// the default constructor of AA calls the default constructors of X and Y
// but those constructors do not call the constructor of B because B is a virtual base
AA a; // a.n == 3
// the default constructor of X calls the constructor of B
X x; // x.n == 1
二次
当涉及虚拟继承时,类成员的非限定名称查找的特殊规则为%28,有时称为主导规则%29,请参见不合格[医]查找#成员[医]功能[医]定义...
公共继承
当类使用public
成员访问说明符要从基类派生,基类的所有公共成员都可以作为派生类的公共成员访问,而基类的所有受保护成员都可以访问,因为基类的受保护成员%28,基类的受保护成员都是不可访问的,除非将%29视为好友。
公共继承模型面向对象编程的子类型关系:派生类对象是-A基类对象。对派生对象的引用和指针预期可用于任何期望引用或指向其公共基%28的代码(参见LSP%29或DBC派生类应保持其公共基的类不变量,不应强化任何先决条件或削弱其成员函数的任何后置条件。覆盖...
保护继承
当类使用protected
成员访问说明符要从基派生,基类中的所有公共成员和受保护成员都可以访问,因为派生类%28的受保护成员不能访问基的私有成员,除非与%29为好友。
受保护的继承可用于“受控多态”:在派生类的成员内部以及所有进一步派生类的成员中,派生类是-A基:在需要对Base的引用和指针的地方可以使用对派生的引用和指针。
私人继承
当类使用private
成员访问说明符要从基派生,基类中的所有公共成员和受保护成员都可以访问,因为派生类%28的私有成员是不能访问的,除非将%29作为好友。
私有继承通常用于基于策略的设计中,因为策略通常是空类,并且将它们用作基既可以支持静态多态性,也可以利用这些类。空基优化...
私有继承也可以用于实现组合关系%28基类子对象是派生类对象%29的实现细节。使用成员可以提供更好的封装,并且通常是首选的,除非派生类要求访问受保护的成员%28(包括基的构造函数%29),需要覆盖基的虚拟成员,需要在其他基础子对象之前构造基,并在其他基础子对象之后进行析构。需要共享虚拟库或需要控制虚拟库的构造。成员实现组合的使用也不适用于来自参数包或者在编译时通过模板元编程确定基类的标识。
类似于受保护的继承,私有继承也可以用于受控的多态性:在派生%28的成员中,而不是在进一步派生的类%29中,派生的是-A基。
二次
template<typename Transport>
class service : Transport // private inheritance from the Transport policy
{
public:
void transmit() {
this->send(... // send using whatever transport was supplied
}
};
// TCP transport policy
class tcp {
public:
void send(...
};
// UDP transport policy
class udp {
public:
void send(...
};
service<tcp> service(host, port
service.transmit(... // send over TCP
二次
成员名称查找
类成员的非限定和限定名称查找规则将在名称查找...
另见
- 虚函数
- 抽象类
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。