代码

#include<iostream>
using namespace std;
#include<string>
//基类:父类
class Base
{
public:
	Base() { cout << "create base "  << name<<endl;}
	Base(int i) { cout << i << "Create Base" << endl; }
	~Base()	{ cout << "drop base " << name << endl; }
	void BaseFun() { cout << "call BaseFun\n"; }
	//一个int占4个字节,以下三个int,共占12字节
	int index{ 0 };
	int x{ 0 };
	int y{ 0 };
	string name{ "BaseName" };
	void Test() { cout << "BaeTest" << endl; }
protected://自己和派生类
	int pid{ 0 };
	void PFunc() {
		cout << "Base::PFunc called" << endl;
	};
private:
	int pri{ 0 };
};

//派生类A继承了Base成员变量和函数
class A :public Base
{
public://默认调用无参构造
	A() :Base(100)//设置选用不同的基类构造函数
	{ cout << "create A" <<name<< endl; }
	~A() { cout << "drop A" <<name<< endl; }
	void AFunc() { cout << "Afunc" << endl; }
	void Test() { cout << "Atest" << endl; }
	int a_index{ 0 };
	string name{ "AName" };//派生类重新定义name
};

//保护继承Base的public变派生类的protected
class ProClass :protected Base
{
public:
	ProClass() { 
		this->index++; 
		this->pid++;
		PFunc();
	}
	int pro_index{ 0 };
};

class ProClassChild :public ProClass
{
public://可以访问Base的pub和pro
	ProClassChild() { this->PFunc(); }
};

//私有继承
class PriClass :private Base
{
public:
	PriClass() { this->PFunc(); }
};

class PriClassChild :public PriClass
{
//不能访问Base中任何成员和方法
};
int main()
{
	Base b;
	cout << sizeof(b) << ":" <<&b << endl;//12字节,没问题
	{
		cout << "======================A begin====================" << endl;
		A a1;
		a1.Test();
		a1.Base::Test();
	}
	cout << "======================A end====================" << endl;
	/*cout << "======================A===================="<<endl;
	A a1;
	a1.index++;
	//派生类访问基类的成员变量和函数
	cout << a1.index << endl;
	cout << "调用函数:" << endl;
	a1.BaseFun();
	a1.AFunc();*/

	{
		ProClass pc;
		pc.pro_index;
	}
	system("pause");


}

继承的基本概念

继承允许我们根据一个已有的类(基类或父类,如 Base)来定义一个新的类(派生类或子类,如 A, ProClass)。它的主要目的是实现代码的重用和功能扩展。派生类自动获得基类的所有成员(变量和函数),并可以添加自己新的成员,或者修改基类成员的行为(通过重写,但本例未展示)。

  • 代码体现: 类 A 通过 : public Base 语法公开继承了 Base 的所有 public 和 protected 成员。

类成员的访问控制

  • public (公有): 可以被任何函数访问。
  • protected (保护): 只能被这个类自身和它的派生类访问。外部代码无法访问。例如 Base 中的 pid 和 PFunc(),A 和 ProClass 的内部可以访问它们,但 main 函数中不行。
  • private (私有): 只能被这个类自身访问。即使是它的派生类也无法访问。例如 Base 中的 pri,只有 Base的成员函数能访问它,A 完全不知道它的存在。

继承方式

代码体现:

  • class A : public Base -> A 的对象在 main 中可以调用 BaseFun() 和访问 index。
  • class ProClass : protected Base -> ProClass 的对象在 main 中不能调用 BaseFun() 或访问 index(因为它们变成了 protected),但其派生类 ProClassChild 可以。
  • class PriClass : private Base -> PriClass 的对象在 main 中不能访问 Base的任何成员,其派生类 PriClassChild 也不能。

派生类的内存模型

一个派生类对象的内存包含两部分:

  • 基类子对象 (Base subobject): 继承自基类的所有数据成员。
  • 派生类部分: 派生类自己定义的新数据成员。
    代码体现:
  • sizeof(b) 打印 40(在64位系统上,string 通常占32字节,3个 int 占12字节,内存对齐到8的倍数可能是40字节)。
  • A a1; 的大小会比 Base 更大,因为它包含了 Base 的所有成员 (index, x, y, name) 再加上自己的成员 (a_index, name)。注意,派生类中与基类同名的成员变量是两个不同的变量,存放在内存的不同位置。

构造与析构的顺序

对象的创建和销毁遵循严格的顺序,这是由编译器自动管理的。

  • 构造顺序 (Construction Order):

基类部分: 调用基类的构造函数。
派生类部分: 调用派生类的构造函数。
输出: create base -> create A

  • 析构顺序 (Destruction Order): 与构造顺序完全相反。

派生类部分: 调用派生类的析构函数。
基类部分: 调用基类的析构函数。
输出: drop A -> drop base

名字遮蔽 (Name Hiding)

如果派生类中定义了与基类同名的成员(变量或函数),那么基类中的那个成员会被“遮蔽”起来。

  • 在派生类中,直接使用名字默认访问的是派生类自己的成员。如果需要访问被遮蔽的基类成员,需要使用作用域解析运算符 ::,例如 a1.Base::name。

  • 代码体现: Base 和 A 都有一个 string name;。在 A 的对象 a1 中,a1.name 访问的是 A::name (“AName”),而要访问基类的名字则需要 a1.Base::name (“BaseName”)。

基类不同构造函数的处理

当基类有多个构造函数时,派生类需要明确指定调用哪一个基类构造函数。这通过在派生类构造函数的初始化列表中调用基类构造函数来实现。

#include <iostream>
#include <string>
using namespace std;

class Base {
public:
    // 默认构造函数
    Base() : x(0), y(0), name("Default") {
        cout << "Base default constructor" << endl;
    }
    
    // 带参数的构造函数
    Base(int x, int y, string name) : x(x), y(y), name(name) {
        cout << "Base parameterized constructor" << endl;
    }
    
    // 拷贝构造函数
    Base(const Base& other) : x(other.x), y(other.y), name(other.name) {
        cout << "Base copy constructor" << endl;
    }
    
    void display() {
        cout << "Base: x=" << x << ", y=" << y << ", name=" << name << endl;
    }
    
protected:
    int x, y;
    string name;
};

class Derived : public Base {
public:
    // 派生类默认构造函数,隐式调用基类默认构造函数
    Derived() : z(0) {
        cout << "Derived default constructor" << endl;
    }
    
    // 派生类构造函数,显式调用基类带参数的构造函数
    Derived(int x, int y, string name, int z) : Base(x, y, name), z(z) {
        cout << "Derived parameterized constructor" << endl;
    }
    
    // 派生类拷贝构造函数,显式调用基类拷贝构造函数
    Derived(const Derived& other) : Base(other), z(other.z) {
        cout << "Derived copy constructor" << endl;
    }
    
    void display() {
        Base::display();
        cout << "Derived: z=" << z << endl;
    }
    
private:
    int z;
};

int main() {
    cout << "=== 创建派生类默认对象 ===" << endl;
    Derived d1;
    d1.display();
    
    cout << "\n=== 创建派生类参数化对象 ===" << endl;
    Derived d2(10, 20, "Test", 30);
    d2.display();
    
    cout << "\n=== 创建派生类拷贝对象 ===" << endl;
    Derived d3 = d2;
    d3.display();
    
    return 0;
}

更多推荐