赞
踩
提问一: 当创建派生类的对象时,是先调用派生类的构造函数?还是先调用基类的构造函数呢?
提问二: 当创建派生类的对象后,派生类对象的成员属性是在调用函数前实例化?还是调用后实例化呢?
当创建一个派生类的对象时,构造函数的调用顺序遵循特定的规则,以确保所有基类成员和成员对象都被正确地初始化。以下是构造顺序:
①基类构造: 若存在多个直接基类,它们将按照继承列表中的顺序被构造。
②成员对象: 在所有直接基类构造函数执行完毕后,派生类中的成员对象(非静态)按照它们在类定义中声明的顺序被构造。
③派生类构造 派生类自己的构造函数体执行。
示例如下:
#include <iostream> using namespace std; class Base1 { public: Base1() { cout << "Base1 constructor called." << endl; } }; class Base2 { public: Base2() { cout << "Base2 constructor called." << endl; } }; class Derived : public Base1, public Base2 { public: Derived() { cout << "Derived constructor called." << endl; } }; int main() { Derived d; // 构造Derived对象 system("pause"); return 0; }
输出结果是:
Base1 constructor called.
Base2 constructor called.
Derived constructor called.
这个例子中,Derived类有两个直接基类Base1和Base2。构造顺序如下:
1. Base1的构造函数首先被调用。
2. Base2的构造函数。
3. Derived类中的成员对象(如果有的话)。
4. Derived自己的构造函数体。
析构顺序即资源被释放的顺序,刚好和构造顺序相反
①派生类析构 ②成员对象析构 ③基类析构
示例代码如下:
#include <iostream> using namespace std; class Base1 { public: Base1() { cout << "Base1 constructor called." << endl; } ~Base1() { cout << "Base1 destructor called." << endl; } }; class Base2 { public: Base2() { cout << "Base2 constructor called." << endl; } ~Base2() { cout << "Base2 destructor called." << endl; } }; class Derived : public Base1, public Base2 { public: Derived() { cout << "Derived constructor called." << endl; } ~Derived() { cout << "Derived destructor called." << endl; } }; int main() { { Derived d; // 构造Derived对象 } // d对象作用域结束,开始析构 system("pause"); return 0; }
输出结果为:
Base1 constructor called.
Base2 constructor called.
Derived constructor called.
Derived destructor called.
Base2 destructor called.
Base1 destructor called.
在这个例子中,析构函数的调用顺序如下:
1. Derived的析构函数首先被调用。
2. Derived中的成员对象(如果有的话)的析构函数,按照它们声明的逆序。
3. Base2的析构函数,因为它在继承列表中位于Base1的右边。
4. Base1的析构函数。
PS:右边是指派生类继承列表的顺序
class Derived : public Base1, public Base2{}
Base2就是在右边
私有继承是一种继承方式,它使得基类中的公有成员(public)和保护成员(protected)在派生类中变为私有成员(private),继承时使用关键字private
即:
1. 基类的公有和保护成员在派生类中不可直接访问,但可以在派生类的成员函数中使用。
2. 私有继承通常用于实现细节的隐藏,将基类作为辅助实现,而不是作为接口的一部分。
示例代码如下:
#include <iostream> using namespace std; class Base { public: Base() { cout << "Base constructor called." << endl; } void publicFunc() { cout << "Public function of Base." << endl; } }; class Derived : private Base {//私有继承 public: // 可以提供一个公有函数来调用基类的公有函数 void accessPublicFunc() { publicFunc(); } // 派生类的构造和析构 Derived() { cout << "Derived constructor called." << endl; } }; int main() { Derived d; d.accessPublicFunc(); // 正确:通过派生类提供的接口访问基类公有函数 // d.publicFunc(); // 错误:在派生类中,基类的公有成员是私有的 system("pause"); return 0; }
保护继承是一种继承方式,当一个类使用保护继承时,基类中的公有成员(public)和保护成员(protected),继承时使用关键字protected
,即:
1. 不能被派生类的对象直接访问调用
2. 可以在派生类的成员函数和友元函数中访问。
3. 派生类的派生类(即基类的更远派生类)也可以将这些保护成员视为保护成员。
示例代码如下:
#include <iostream> using namespace std; class Base { public: int publicVar; protected: int protectedVar; }; class Derived : protected Base { // 基类中的publicVar和protectedVar现在都是保护成员 }; int main() { Derived d; // d.publicVar = 10; // 错误:publicVar现在是保护成员,不能在Derived对象中直接访问 // d.protectedVar = 20; // 错误:同样,不能直接访问 system("pause"); return 0; }
1.实现细节隐藏:保护继承和私有继承都用于隐藏基类的实现细节,防止派生类外部直接访问基类的成员。
2.基类成员不可直接访问:无论是保护继承还是私有继承,基类中的公有成员都不能在派生类的对象中直接访问。
3.派生类成员函数访问权限:在派生类中,无论是保护继承还是私有继承,派生类的成员函数都可以访问从基类继承来的成员。
访问权限:
对派生类派生类的可见性:
设计意图:
友元关系:
构造和析构:
无论是保护继承还是私有继承,基类的构造函数和析构函数仍然可以被派生类的对象调用,以完成对象的构造和析构。
切除问题(Pruning)指的是当通过基类指针或引用访问派生类对象时,无法访问派生类中新增的成员或重写的方法。
示例代码如下:
#include <iostream> using namespace std; class Base { public: virtual void show() { cout << "Base show" << endl; } }; class Derived : public Base { public: void show() override { cout << "Derived show" << endl; } void derivedOnly() { cout << "Only in Derived" << endl; } // 新增的方法 }; void someFunction(Base& baseRef) { baseRef.show(); // 可正确调用 // baseRef.derivedOnly(); // 错误:无法通过基类引用访问 Derived 的特有成员 } int main() { Derived d; someFunction(d); // 通过基类引用传递派生类对象 system("pause"); return 0; }
在这个例子中,尽管someFunction接收的是Base类型的指针,实际上传入的是Derived类型的对象。但是,由于基类指针的限制,我们无法通过它来访问Derived类特有的成员derivedOnly,这就是切除问题。
指一个派生类可以同时从多个基类继承属性和方法的能力,这使得派生类可以组合来自多个基类的特性。
示例代码如下:
#include <iostream> using namespace std; // 基类:动物(Animal) class Animal { public: virtual void makeSound() { cout << "Animal sound" << endl; } }; // 基类:鸟类(Bird) class Bird : public Animal { public: void makeSound() override { cout << "Bird chirp" << endl; } // 鸟类特有的叫声 void fly() { cout << "Bird is flying" << endl; } // 鸟类特有的飞行行为 }; // 基类:狗类(Dog) class Dog : public Animal { public: void makeSound() override { cout << "Dog bark" << endl; } // 狗类特有的叫声 void run() { cout << "Dog is running" << endl; } // 狗类特有的奔跑行为 }; // 派生类:鸡类(Chicken),它同时继承自动物(Animal)和鸟类(Bird) class Chicken : public Bird, public Dog { public: // 鸡类可以重写或添加新的行为 void makeSound() override { cout << "Chicken cluck" << endl; } // 鸡类特有的叫声 void layEgg() { cout << "Chicken is laying an egg" << endl; } // 鸡类特有的下蛋行为 }; int main() { Chicken myChicken; myChicken.makeSound(); // 调用鸡类的makeSound,输出 "Chicken cluck" myChicken.fly(); // 调用鸟类的fly,输出 "Bird is flying" myChicken.run(); // 调用狗类的run,输出 "Dog is running" myChicken.layEgg(); // 调用鸡类特有的layEgg,输出 "Chicken is laying an egg" system("pause"); return 0; }
class FinalClass final {
// code
};
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。