【问题标题】:C++ what's the correct way to define static memberC++定义静态成员的正确方法是什么
【发布时间】:2019-01-06 05:05:51
【问题描述】:

我正在尝试在普通成员函数中使用静态成员。但是编译器报告了一些错误。请看一下这段代码

#include <memory>

template<typename T>
class MyClass {
private:
  static std::allocator<T> alloc;
  T *p;
public:
  void assign(T e) {
    p = alloc.allocate(1);
    alloc.construct(p, e);
  }
};

这就是我使用它的方式:

#include 'myclass.h'

int main() {
  MyClass<int> cls;
  cls.assign(4);

};

编译器给出这个错误:

/Users/liuziqi/CLionProjects/cpplearning/src/tt.h:17:9: warning: instantiation of variable 'MyClass<int>::alloc' required here, but no definition is available [-Wundefined-var-template]
    p = alloc.allocate(1);
        ^
/Users/liuziqi/CLionProjects/cpplearning/src/main.cpp:49:7: note: in instantiation of member function 'MyClass<int>::assign' requested here
  cls.assign(4);
      ^
/Users/liuziqi/CLionProjects/cpplearning/src/tt.h:13:28: note: forward declaration of template entity is here
  static std::allocator<T> alloc;
                           ^
/Users/liuziqi/CLionProjects/cpplearning/src/tt.h:17:9: note: add an explicit instantiation declaration to suppress this warning if 'MyClass<int>::alloc' is explicitly instantiated in another translation unit
    p = alloc.allocate(1);

我不知道哪一部分是错的.....我已经定义了静态成员和任何成员函数都应该能够使用它。此错误是否与 模板 相关? (我刚刚学习了模板,不确定我是否正确使用它。)

【问题讨论】:

    标签: c++


    【解决方案1】:

    除了回答“如何修复它”问题(之前肯定已经回答过很多次)之外,我将尝试描述警告所指的内容......

    因为 MyClass 是一个模板,所以编译器希望模板化类的所有代码都可以在同一个文件中使用 (myclass.h)。由于您只在 myclass.h 中声明但未定义 alloc,编译器会假定您犯了一个错误。它不是绝对必须存在的(因此是 warning 而不是 error),如果您在别处定义变量,您可以禁用该警告,但几乎可以肯定这只是一个错误。

    如果您使用的是 c++17,处理此问题的最简单方法是将静态成员声明为内联,因此将在此处定义:

      static inline std::allocator<T> alloc;
    

    直播:https://godbolt.org/g/cr1aUP

    在 C++17 之前,您将在 myclass.h 中显式定义变量:

    template<typename T>
    std::allocator<T> MyClass<T>::alloc;
    

    直播:https://godbolt.org/g/2Znqst

    【讨论】:

    • 我对这里的“声明”和“定义”有点困惑。我认为我在类模板中的 alloc 声明已经是一个“定义”,因为这就是我通常定义类成员的方式。为什么还需要在外面定义呢? (它看起来和我在模板中的“声明”一样......这里有什么不同?)。是模板的问题吗? (也就是说,如果我们这里写的不是模板,而是一个类,那么类里面的定义就足够了)
    • 静态变量每个类只定义一次,而不是每个对象一次。在 C++17 之前,这需要类定义之外的静态成员定义。如果您熟悉的话,它与extern 在非课堂环境中的工作方式非常相似。如果这不是在模板情况下,在另一个文件(.cpp 文件)中定义是很正常的,但是因为需要为类 MyClass 的每个 实例化 定义静态变量 需要一个,MyClass 需要一个不同的,等等...然后在 .h 文件中需要定义,因此实例化...
    • 调用者可以生成代码来为正在使用的模板类的确切实例化类型创建静态成员。
    猜你喜欢
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-14
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多