【问题标题】:Call static member from inherited class instance从继承的类实例调用静态成员
【发布时间】:2025-12-30 07:25:15
【问题描述】:

我有两个类,YXY 包含一些静态成员——我试图通过 X 实例访问它们:

template <class T>
class Y {
public:
    Y() {
        i = 0;
        v = std::vector<int>(10, 10);
    }
    static int value() {
        return v[i];
    }
private:
    static int i;
    static std::vector<int> v;
};

class X : public Y<X> {
public:
    X() {
    }
};

int main() {
    X *x(new X());
    std::cout << x->value() << std::endl;
}

即使编译了,也没有正确链接:

$ g++ t.cpp
/tmp/ccB4ijzw.o: In function `Y<X>::Y()':
t.cpp:(.text._ZN1YI1XEC2Ev[Y<X>::Y()]+0x11): undefined reference to `Y<X>::i'
t.cpp:(.text._ZN1YI1XEC2Ev[Y<X>::Y()]+0x4a): undefined reference to `Y<X>::v'
/tmp/ccB4ijzw.o: In function `Y<X>::value()':
t.cpp:(.text._ZN1YI1XE5valueEv[Y<X>::value()]+0x6): undefined reference to `Y<X>::i'
t.cpp:(.text._ZN1YI1XE5valueEv[Y<X>::value()]+0x10): undefined reference to `Y<X>::v'
collect2: ld returned 1 exit status                                             

上下文(如果重要):

我正在尝试编写一个内存管理器——class Y——它静态地保存一个内存池,以便class X 的所有实例都使用Y 提供的内存块。

我不确定这是否是我想要做的最好的方法,但这是我迄今为止想到的最优雅的方法。非常欢迎任何想法。

【问题讨论】:

    标签: c++ static static-methods static-members


    【解决方案1】:

    必须定义和声明静态数据成员。如果这是一个普通的课程,你会这样做:

    // header:
    class C {
        static int i;
    };
    
    // source:
    int C::i = 3;
    

    对于类模板,您通常不会将代码放在源文件中,因此您应该这样做:

    // header:
    template <class T>
    class C {
        static int i;
    };
    
    template <class T>
    int C<T>::i = 3;
    

    【讨论】:

    • 啊,那就这样吧。我不知道;非常感谢!只是另一个问题。由于我有两个以上的成员,是否有任何合适的语法允许多个定义——而不是不断重复template &lt;class T&gt;?无论如何,它工作得很好!
    • @Rubens - 我不知道。但只需敲几下键即可复制和粘贴该行。
    【解决方案2】:

    由于函数value 是静态的,它对class Y 的所有实例都是通用的。调用静态成员函数的方式是这样的

    std::cout << Y<X>::value() << std::endl;
    

    不(这不是非法的,但这不是一个好习惯。为什么要让函数静态,我还是要这样做?。)

    std::cout << x->value() << std::endl;
    

    此外,您必须定义所有静态成员。类似的东西

    template <class T>
    int Y<T>::i = 0;
    
    template <class T>
    std::vector<int> Y<T>::v(0);
    

    【讨论】:

    • 我记得看到一个问题,OP 询问是否应该禁止通过实例访问成员,而答案表明不是。 (无论如何,不​​是我对你的帖子投反对票)。
    • 通过实例访问它们并不违法。但是,如果您要这样做,为什么还要让函数成为静态的呢?这是为了表明它属于类而不是实例。
    • 是的,我只是指出这是不被禁止的——因为在试图解决我的问题时看到一个帖子说这个。