类定义末尾的 : 是继承声明起始符,后接访问限定符和基类名,不可省略或替换;public/protected/private 控制基类成员在派生类中的可见性;它与 :: 作用域解析符和构造函数初始化列表中的 : 语义完全不同。

类定义末尾的 : 是继承声明起始符
它不是标点停顿,而是 C++ 语法中明确告诉编译器“接下来要写继承关系”的符号。紧随其后的必须是访问限定符(public、protected 或 private),再之后是基类名。漏掉这个 :,编译器直接报错,比如 expected ':' before '{'。
-
class Derived : public Base中的:是必需的,不能省略或替换成其他符号 - 如果省略访问限定符(如写成
class D : B),对class默认按private继承,行为往往不符合预期 - 若基类有多个,用逗号分隔,但每个前面仍需各自带
:和访问限定符,例如class D : public A, protected B
public、private、protected 决定基类成员在派生类中的可见性
冒号后写的那个关键字,不是修饰派生类本身,而是控制“基类成员如何被带入派生类”。它直接影响后续能否访问、能否被进一步继承、能否被外部调用。
-
public继承:基类的public成员在派生类中仍是public,protected保持protected,private不可访问 —— 这是最常用、最符合“is-a”语义的方式 -
private继承:所有基类public和protected成员在派生类中都变成private,外部和子类都无法访问;这其实更接近“has-a”,应优先考虑组合而非这种继承 -
protected继承:基类public和protected都降为protected,仅派生类及其后代可访问,外部不可见
别把类定义里的 : 和作用域解析符 :: 搞混
类名后单个 : 只出现在类定义头部,专用于继承声明;而 :: 是双冒号,是作用域解析符,用在定义体内部或类外,比如静态成员定义、全局变量引用、命名空间限定。
- 错误写法:
class D : public B { void f() { B::m_x = 1; } };—— 这里::没问题,但和开头的:完全无关 - 混淆典型:
class D: public B::—— 语法错误,::不能出现在继承列表里 - 真正容易漏的是:在类外定义成员函数时,要用
Derived::func(),这里的::和类定义开头的:毫无语法关联,只是碰巧都用了冒号字符
构造函数初始化列表里的 : 是另一回事
类定义末尾的 : 和构造函数实现里冒号开头的初始化列表,长得像,但语义完全不同。后者不是继承相关,而是对象成员/基类子对象的初始化入口。
- 例如
Derived::Derived(int x) : Base(x), m_y(x * 2) { }—— 这里的:属于构造函数语法,和类声明中的:各自独立 - 如果在派生类构造函数里忘了调用基类构造函数(比如漏掉
Base(x)),可能触发默认构造,导致m_id未按预期初始化,但编译器不一定报错 - 初始化列表中的顺序必须和类中成员声明顺序一致,否则实际初始化顺序会出人意料,和这个
:本身无关,但新手常在这里栽跟头
实际写代码时,最常忽略的是继承方式的显式声明和基类构造函数的传递。这两个点不体现在语法错误上,但会导致运行时行为异常,调试起来比编译失败更费时间。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











