类定义需注意三处关键:访问标号后必须加冒号,构造函数不可写返回类型,头文件中不得实现非内联成员函数,否则引发隐蔽编译或链接错误。

类定义必须写在 class 关键字后面,且名字后紧跟花括号
很多人卡在第一行就报错,比如写成 class MyClass { }; 却漏了分号——这在 C++11 之后是合法的,但若类里有成员函数定义、模板或继承,漏分号会引发后续一连串解析错误。更常见的是把类体写成 class MyClass { public: int x; } myObj;,以为这样能同时定义类和变量,结果 myObj 变成全局变量,而类名本身没被复用,后续 MyClass obj; 会报 “use of undeclared identifier”。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 始终把类定义单独成块:
class MyClass { /* 成员 */ };,分号不能省(尤其头文件中) - 类内只声明成员,不初始化非静态数据成员(C++11 允许
int x = 42;,但老编译器不认) - 构造函数写在类内时,用
= default或= delete显式控制,别留空体MyClass() {}而不加public:
public / private 不是函数,是访问标号,必须带冒号
新手常把 public 当成函数调用写成 public();,或者忘记加冒号,导致编译器把后续成员全当成私有,甚至报 “expected unqualified-id before ‘int’” 这类迷惑错误。访问标号不是作用域语句,它只影响紧随其后的成员,直到下一个标号或类结束。
实操建议:
立即学习“C++免费学习笔记(深入)”;
-
public:、private:、protected:后面必须跟英文冒号,且独占一行或紧跟换行(不要写成public: int x;在同一行,虽合法但易读性差) - 一个标号生效范围从它出现位置开始,到下一个标号或
};为止,中间不能跨函数体中断 - 类默认是
private:,所以没写任何标号时,所有成员都无法从外部访问
构造函数名必须和类名完全一致,且不能有返回类型
写成 void MyClass() {} 或 MyClass() -> void {} 都会报错:前者被当普通函数(重定义冲突),后者语法非法。更隐蔽的问题是大小写不一致,比如类叫 StringBuffer,却写了 stringbuffer() —— C++ 区分大小写,直接变成未定义构造函数,StringBuffer s; 编译不过。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 构造函数没有返回类型,连
void都不能写;析构函数同理,但要加波浪号:~MyClass() - 如果类模板化,构造函数名仍用原类名,不带模板参数:
template<typename t> class Vec { Vec(); };</typename>,不是Vec<t>()</t> - 用委托构造时,调用必须在初始化列表里:
MyClass() : MyClass(0) {},不能在函数体内写this->MyClass(0);
头文件里定义类,千万别在其中实现非内联函数
把 void MyClass::doWork() { /* 大段代码 */ } 直接写在头文件的类定义里,会导致每个包含该头的 .cpp 文件都生成一份函数定义,链接时报 “multiple definition of `MyClass::doWork()`”。这不是警告,是硬性链接失败。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 头文件(.h 或 .hpp)只放类声明、内联函数(用
inline或直接写在类内)、模板定义 - 普通成员函数实现一律挪到 .cpp 文件里,哪怕只有两行也要拆开
- 如果真想内联,确保函数体在类内定义,或显式加
inline且定义在头文件中(并保证只被包含一次)
类定义看着简单,但访问标号的冒号、构造函数的返回类型、头文件里的函数实现边界——这三个地方出错,往往不会直接告诉你“类写错了”,而是抛出一堆下游错误。盯住它们,比反复检查大括号配对更有效。










