子类声明必须显式指定public、protected或private继承方式,决定父类成员访问权限;构造函数不继承,需在初始化列表中显式调用父类构造函数;同名函数会隐藏而非覆盖父类版本,须用Base::func()访问。
继承方式决定父类成员在子类中的访问权限,必须显式写出,不能省略。C++ 支持三种:public、protected、private,最常用的是 public 继承。
public 继承:父类的 public 成员在子类中仍为 public,protected 保持 protected,private 不可访问protected 继承:父类所有非 private 成员在子类中变为 protected
private 继承(极少用):父类所有非 private 成员在子类中变为 private
错误写法:class Derived : Base —— 缺少冒号和继承关键字,编译报错:expected ‘:’ before ‘{’ token。
C++11 起支持使用 using 声明继承部分构造函数(仅限无默认参数、无重载冲突的情况),但绝大多数场景下,子类需自己定义构造函数,并在初始化列表中调用父类构造函数。
no matching function for call to ‘Base::Base()’
class Base {
public:
Base(int x) : val(x) {}
private:
int val;
};
class Derived : public Base {
public:
Derived(int x, int y) : Base(x), data(y) {} // ✅ 正确:显式调用 Base(int)
private:
int data;
};
子类定义了与父类同名的函数(无论参数是否相同),父类该名字的所有重载版本都会被**隐藏**,而非重载或覆盖。这是初学者最常踩的坑。
Base::func()
override,才是覆盖(override);否则是隐藏(hiding)class Base {
public:
void print() { std::cout << "Base\n"; }
void print(int x) { std::cout << "Base " << x << "\n"; }
};
class Derived : public Base {
public:
void print() override { std::cout << "Derived\n"; } // 隐藏了 Base::print() 和 Base::print(int)
// 下面这行会编译失败,除非显式写 Base::print(42)
// void foo() { print(42); }
void foo() { Base::print(42); } // ✅ 显式调用
};
当两个父类都继承自同一个祖父类,而子类又同时继承这两个父类时,若不使用 virtual,子类会包含两份祖父类子对象,引发二义性和内存冗余。
virtual public Base

典型错误现象:error: ‘Base’ is an ambiguous base of ‘Derived’,或访问 Base 成员时报二义性。
sizeof 检查布局,用 gdb 或 clang -cc1 -ast-dump 看实际符号解析路径。