2010-06-14 109 views
3

我在C++中的一些概念中变得非常困惑。对于例如:我有以下两个文件静态初始化混淆

//file1.cpp 
class test 
{ 
    static int s; 
    public: 
    test(){s++;} 
}; 

static test t; 
int test::s=5; 

//file2.cpp 
#include<iostream> 
using namespace std; 
class test 
{ 
    static int s; 
    public: 
    test(){s++;} 
    static int get() 
    { 
    return s; 
    } 
}; 

static test t; 

int main() 
{ 
    cout<<test::get()<<endl; 
} 

现在我的问题是:
1.如何两个文件成功链接,即使他们有不同的类定义?
2.两个类的静态成员是否相关,因为我得到的输出为7.

请解释这个静态的概念。

回答

3

它们之间的链接是因为链接器几乎不了解C++语言。但是,如果你这样做,你打破了一个定义规则,你的程序的行为将是未定义的。编写无效的代码不是学习C++的好方法。另外,你似乎有很多关于静态变量的问题 - 这个概念实际上并不那么复杂 - 你使用的C++教科书不能很好地解释它吗?

+0

Ok..Now假设我写在同一个类定义两个文件。 那我的第二个问题呢? 这两个类的静态成员是相关的吗? – 2010-06-14 10:31:14

+0

@Happy只能有一个名称为test的类,所以只能有一个静态变量。其他任何东西都是连接器产生的人工制品。 – 2010-06-14 10:33:18

+0

我正在使用Bruce Eckel的C++中的Thinking。其实我正在阅读schwarz计数器技术的静态初始化命令失败,但我无法理解为解释该技术而编写的代码。 如果你有这本书,你能解释一下这个代码吗? – 2010-06-14 10:34:27

1

这些类(就链接器而言)是相同的。 get()只是链接器从不会看到的内联函数。

类中的静态不会将成员限制为文件作用域,但会使其成为全部类实例的全局对象。

[编辑]你会得到一个链接器错误,如果你将int test::s=5;也放入第二个文件中。

1

静态是C++中的一种奇怪的野兽,根据上下文的不同有着不同的含义。

在File1.cpp中,类定义中的“static int s”表示s是一个静态成员,即对于所有测试实例都是通用的。

但是,“静态测试t”具有不同的含义:静态全局变量仅存在于编译单元中,并且不会被其他单元看到。这是为了避免链接器混淆,如果你使用两个不同的东西同名。在现代C++中,应当使用匿名命名空间是:

namespace 
{ 
    test t; 
} 

这意味着T内File1.cpp和T内File2.cpp是单独的对象。

在File2.cpp中,您还定义了一个静态方法get:静态方法是属于类而不是实例的方法,并且只能访问该类的静态成员。

最后一次使用静态,你没有在你的例子中使用的是本地静态变量。局部静态变量初始化它首先执行的时间,并保持整个执行它的价值,有点像一个本地范围的全局变量:

int add() 
{ 
    static value = 0; 
    value++; 
    return value; 
} 

调用add()反复将返回1,那么2 ,然后3 ...这个本地静态结构可以用于本地缓存。

0
  1. 即使它们具有不同的类定义,两个文件如何成功链接?

您违反了在不同的翻译单位不同定义同班一个定义规则(ODR)。这调用了可怕的未定义的行为。这意味着代码可以做任何事情,包括但不限于做你想做的事,格式化你的硬盘,或者造成未被认定的日蚀。
请注意,不要求编译器/链接器检测ODR违规。

  • 涉及两个类的静态成员是因为我得到的输出7.
  • 也许他们,也许他们都没有。真的,未定义的行为可能会做任何事情。你看到的只是你的编译器和链接器的实现。
    一个可能的实现将很高兴地将所有对test::s的引用链接到同一个实例,但让每个翻译单元都有 - 并链接到 - 它们自己的t对象。 (由于类只有inline功能,最有可能的连接者甚至从未见过除了test::s和那些t实例test东西。)的C++如何实际工作

    0

    Unnice副作用。使用名称空间使类名与外部不同。

    在过去,我在实践中使用了相当繁琐的规则:每个库和文件必须有一个专用的命名空间以避免这种链接冲突。或者将实用程序类放入主类定义中。无论如何:不要污染全球名称空间,最重要的是要确保整个项目名称的唯一性。 (编写,现在我发现我用几乎逐字概念从Java)。

    我对C的静态在C++中的等价搜索是徒劳的......

    +0

    C++与C有完全相同的静态概念,加上一些。 – 2010-06-14 12:17:17

    +0

    @neil:如何创建* static *方法或类,这些方法或类在编译单元之外是不可见的? C具有函数和数据 - 将* static *应用于它们使其成为本地。 C++有类 - 但我没有找到任何东西来编译本地编译单元的类。 – Dummy00001 2010-06-14 14:15:26

    +0

    非类静态函数在C++中的工作原理与C中的相同。事实上,你不能编译单元本地类静态函数(尽管你当然可以拥有私有函数)并不矛盾我的评论。 – 2010-06-14 15:27:33