Static Cast访问静态const类成员

9Br*_*ker 4 c++ casting

所以昨天我一直在寻找SO而无法找到以下答案.这种情况来自我正在使用的一些代码,但这是MCVE来演示它.

我在A中定义了一个A类,其中只有一个静态const.我已经在标题中初始化了它.

#ifndef A_H_
#define A_H_
class A {
public:
    static const int test = 5;
    ~A(){};
};


#endif /* A_H_ */
Run Code Online (Sandbox Code Playgroud)

然后我有一个类B需要从类A访问公共静态const.在这个例子中,它会将值深度复制到向量.

#ifndef B_H_
#define B_H_

#include "A.h"
#include <vector>
#include <iostream>

class B {
private:
    std::vector<int> testVec;

public:
    B(){

        testVec.push_back((const int)A::test);
        //testVec.push_back(static_cast<const int>(A::test)); //Also works
        //testVec.push_back(A::test); //Doesn't work without forward declaration of const int A::test in main or in this header 
        //(Compiler link error: undefined reference to `A::test')  
        std::cout<< testVec.front() << std::endl;
    }

    ~B(){};
};

#endif /* B_H_ */
Run Code Online (Sandbox Code Playgroud)

然后在main中我简单地调用了B类的构造函数.

#include "B.h"

int main() {

    B b;

    return 0;
}
//Does the cout from ctor of B and prints 5 to the screen. 
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么正常的强制转换或静态强制转换允许我访问这个尚未向前声明的静态const变量.在普通代码中,我会转发声明变量或将其声明为extern,因为它已经被定义.为什么铸造允许我在没有前向声明的情况下访问此变量的原因是什么?(这可能看起来像一个简单的问题,可能有一个简单的答案,但我想在这里进一步了解我的知识).

编译器链接错误的输出是:

Invoking: Cygwin C++ Linker
g++  -o "S_Test_p1.exe"  ./src/S_Test_p1.o   
./src/S_Test_p1.o:S_Test_p1.cpp:(.rdata$.refptr._ZN1A4testE[.refptr._ZN1A4testE]+0x0): undefined reference to `A::test'
collect2: error: ld returned 1 exit status
make: *** [makefile:47: S_Test_p1.exe] Error 1
Run Code Online (Sandbox Code Playgroud)

我的主要问题是为什么铸造工作而不是解决方案是在main或Bh中定义A :: test(我知道它有效).我明白这是可以接受的.主要问题是关于不可接受的方式,即铸造.在幕后为什么投射工作链接?

asc*_*ler 7

static类中的成员static const int test = 5;的声明是声明而不是定义,即使它具有初始化器.声明通常应该有相应的定义.这个定义看起来像const int A::test;(这不是"前向声明".)

但是,还有一个额外的规则,即static const如果只使用其值,则不需要定义整数类的类成员,不使用其地址,并且没有引用绑定到它(这与获取其地址类似).

你正在打电话的功能是void std::vector<int>::push_back(const int&);.因此A::test直接传递会将函数参数引用直接绑定到对象,并需要定义.

另一方面,如果传递(const int)A::test或者static_cast<const int>(A::test),则强制int使用值创建临时值A::test,并且引用将绑定到该临时值.因此,在这种情况下,A::test没有必要定义.

注意在C++ 17中,A::test在任何情况下都不需要定义,因为static在类定义中具有初始化器的类成员隐式地是inline变量和定义.

在此之前,请确保static在某些*.cpp文件中定义所有类成员,以防您以需要定义的方式使用它们.