访问”和“初始化本质区别以及C++静态成员变量定义位置详解

发布于:2025-04-21 ⋅ 阅读:(75) ⋅ 点赞:(0)

💡 1.访问”和“初始化本质区别:

  • 访问 protectedNumDerived 作为 Base 的子类,是可以在自己的函数中访问 protectedNum 的。
  • 初始化 protectedNum:只能通过 Base 的构造函数来初始化,因为它是 Base 拥有的成员,不是 Derived 的成员,Derived 的初始化列表里不能直接初始化它。

📘 展开讲一讲:

🧱 protectedNum 是谁的成员?

它属于 Base 类:

class Base {
protected:
    int protectedNum;
};

🔍 能访问它吗?

是的,只要是在 Derived 类的成员函数里,就可以直接访问它,因为继承关系允许子类访问 protected 成员。

✅ 这就像你住在你爸的房子里,屋子里东西你可以随便用,但你不能在房子建好之前,自己去改它的结构。


❌ 为什么不能在 Derived 构造函数初始化列表里初始化 protectedNum

这是因为:

  • 初始化列表只允许你初始化你自己的成员变量
  • protectedNumBase 的成员;
  • 所以你只能通过调用 Base 的构造函数去初始化它。

你写的这句:

Derived(int num) : protectedNum(num) {}

相当于说:我不调用 Base 构造函数,我直接改你 Base 的东西 —— C++ 不允许这样。

✅ 正确方式是这样:

Derived(int num) : Base(num) {}

或者直接赋值
     Derived(int num) 
    {
        protectedNum = num;
    };

Base 自己初始化它的成员,你只是告诉 Base 你要传什么。


✍️ 类比打个比方:

你(Derived)住在爸妈家(Base),你可以用家里的冰箱(protected 成员),但盖房子(初始化)的时候得让你爸(Base 构造函数)去决定冰箱要不要装、装在哪里,你不能越权。

2.C++ 静态成员变量定义位置详解

一、普通类中的静态成员变量

1. 定义方式
class MyClass {
public:
    static MyClass instance;
    MyClass();
    ~MyClass();
};
  • 在头文件 .h 中:这是声明
  • 在源文件 .cpp 中:必须提供定义
MyClass MyClass::instance;
2. 为什么要放 .cpp
  • 头文件可能被多个 .cpp 包含,如果在 .h 中定义,会导致多重定义
  • C++ 需要在一个且只有一个地方定义并分配静态成员变量的内存
3. 总结
问题 答案
静态变量在类中声明是否自动定义?
定义应放哪里? .cpp
可以放 .h 吗? 不推荐,会造成链接错误

二、模板类中的静态成员变量

1. 定义方式
template <typename T>
class MyTemplate {
public:
    static int count;
};

template <typename T>
int MyTemplate<T>::count = 0; // 必须放在 .h 文件中!
2. 为什么要放 .h
  • 模板类不是提前编译好的,而是使用时编译器才生成代码(模板实例化)
    • 每种类型的实例(例如 MyTemplate<int>MyTemplate<double>)都是独立的类
  • 编译器在看到 MyTemplate<int> 时,需要能立即看到静态成员的定义
3. 使用 inline 避免多重定义(C++17 起)
template <typename T>
inline int MyTemplate<T>::count = 0;
4. 总结
特性 普通类 模板类
是否提前确定 否(实例化时生成)
静态变量定义放哪 .cpp .h
多重定义风险 无,每个模板类型分开
推荐方式 类外定义一次 类内 + inline(C++17)

三、类内初始化的例外:常量静态成员

可以在类内定义的情况:
  • static constexprstatic const int 这类字面值常量:
class Config {
public:
    static const int MaxValue = 100; // OK
};
非 constexpr 类型(如 std::string)仍需类外定义:
class Config {
public:
    static const std::string name; // 声明
};

// .cpp 中定义
const std::string Config::name = "App";

四、实践建议

  • 🧠 普通类静态成员变量 ➜ 放 .cpp
  • 🧠 模板类静态成员变量 ➜ 放 .h,或加 inline(C++17 起)
  • 🧠 所有类的静态成员 ➜ 不要忘记定义(否则链接失败)

网站公告

今日签到

点亮在社区的每一天
去签到