1

我们可以像这样声明一个类成员:

class Test {
public:
    int a;
}

这就是我们声明的方式,但我想知道变量a是在哪里定义的。

我知道静态类成员,它是静态变量,所以不能在类中定义,应该在类外定义。所以我认为普通类成员应该有一个定义的地方,我猜它是隐式定义普通成员的构造函数。是对的吗?

4

4 回答 4

5

对于非静态数据成员,声明和定义是一回事。

所以我认为普通类成员应该有一个定义的地方,我猜它是隐式定义普通成员的构造函数。

我想我可以看到你来自哪里。对于每个静态数据成员,每种类型只有一个变量实例(对于模板 - 每个模板实例化创建一个不同的类型) - 这就是为什么声明更像是普通变量的外部声明 - 它是说“这个变量将有一个某处的地址 - 请链接器稍后在地址中拼接”。定义_是程序要求编译器为特定翻译单元对象中的变量保留实际内存的地方,链接器将找到该变量,并使其可供其他翻译单元中的代码访问,这些翻译单元知道并根据声明访问该变量。(模板有点复杂)。因此,从程序员的角度,松散地说,静态数据成员定义似乎是触发内存分配并安排构造函数运行的源代码行。一旦你写好了定义,分配和构造都被排序了。

但是,对于非静态数据成员,情况却完全不同——当编译器解析类定义时,仍然没有实际请求在任何地方为这些非静态数据成员提供任何内存,因为还没有该类类型的实例对象. 只有当其他一些代码表明需要对象实例时,编译器才需要安排内存(如果不使用放置new)和构造。换句话说,对于非静态数据成员的定义和分配/构造通常是解耦的——使用单独的源代码。

这一切都以递归方式应用:当对象实例本身是静态的或文件/命名空间范围时,内存和构造(包括类内的数据成员)将在看到定义时安排(不一定执行),如上所述。但很多时候对象实例位于堆栈或堆上。无论哪种方式,数据成员的分配和构造代码都是由创建包含对象的方式驱动的,并且与数据成员的定义无关。

于 2013-03-21T02:40:07.187 回答
0

对象的每个实例都在内存中为该对象分配了一些保留空间。可能在堆存储或堆栈中。

它位于该空间内的特定位置,该对象的每个成员变量都被存储。

于 2013-03-21T02:41:07.627 回答
0

a可以在声明之后、在构造函数中或完全在类之外定义。这是一个示例,显示了a可以定义的所有方式

class Test {
public:
    int a = 5;
    Test() {
        a = 5;
    }
};

int main() {
    Test foo;
    foo.a = 5;

    return 0;
}
于 2013-03-21T02:51:07.890 回答
0

作为一个好的做法,你应该封装你的数据成员并在特定的方法中管理它们的定义,比如 SetA()、GetA(),你可以在构造函数中给出默认值

于 2013-03-21T06:22:56.383 回答