【问题标题】:Using Static Member Function to Access Static Data Member使用静态成员函数访问静态数据成员
【发布时间】:2017-05-26 09:45:28
【问题描述】:

我正在尝试使用静态成员函数访问静态数据成员,以便我可以调用此函数并检索数据成员。目标是增加/减少这个静态数据成员来计算程序中存在多少对象。

作业逐字逐句:

应该提供一个名为 getNumObjects 的静态成员函数,它不接受参数并返回一个 int 值,指示当前存在的 Complex 类型的对象的数量。

到目前为止我的代码:

复杂的.hpp

class Complex{
public:
...
// Get the number of complex objects in the current program
        static int& getNumObjects();
...

private:
...
        static int counter; // static counter
...
}

复杂的.cpp

// Initialize object counter for getNumObjects()
int Complex::counter = 0;
// Get number of objects existing in the current program
static int& Complex::getNumObjects(){
        return counter;
}

testComplex.cpp

// checks to see how many complex objects are open currently
        std::cout << "How many complex objecst are in existence? ";
        int num = Complex::getNumObjects();
        std::cout << num << '\n';
        std::cout << "successful\n";

我不明白为什么编译器总是向我抛出这个错误:

 error: cannot declare member function ‘static int& Complex::getNumObjects()’ to have static linkage [-fpermissive]
 static int& Complex::getNumObjects(){

或者这个错误:

In function ‘int getNumObjects()’:
/../../../ error: ‘counter’ was not declared in this scope
  return counter;
         ^~~~~~~
/../../../ note: suggested alternative: ‘toupper’
  return counter;
         ^~~~~~~
         toupper

我进行了广泛的搜索,我似乎已经初始化了我的私有数据成员以及函数。 getNumObjects() 被声明为一个类,为什么说函数的作用域不对呢?

【问题讨论】:

  • 您究竟为什么要返回对int 的引用?
  • @KinanAlSarmini 以类似的方式,我还有其他函数可以检索其他私有数据成员,这就是为什么我认为我应该只使用引用来尝试访问计数器
  • 更好的办法是在构造函数/析构函数内部增加/减少计数器,而不是返回引用并在外部更新。
  • @KinanAlSarmini 我的构造函数和解构函数有内部计数器,但是出现了第二个问题。移动构造函数和复制构造函数是否意味着创建了一个新对象?
  • 任何构造函数调用都意味着创建了一个新对象。移动构造函数并没有真正说明正在构造的对象的生命周期,它更多的是关于构造对象的生命周期。所以我想说你应该在你可能拥有的任何构造函数中增加计数器。

标签: c++ class static static-members private-members


【解决方案1】:

我不明白为什么编译器总是向我抛出这个错误:

因为您在成员函数定义中重复了static。该函数已声明为static; C++ 语法要求您在 cpp 文件中省略 static

int Complex::counter = 0;
// Get number of objects existing in the current program
int& Complex::getNumObjects(){
    return counter;
}

注意:返回int&amp; 可能不是一个好主意,因为调用者可以在您不知情的情况下修改counter

Complex::getNumObjects() = -123; // <<== returning reference makes this legal

这很糟糕,因为它完全破坏了封装。从本质上讲,您的 counter 最终会像公共成员变量一样被公开。

您应该更改您的函数以返回 int

int Complex::getNumObjects(){
    return counter;
}

【讨论】:

  • 非常感谢您的解释!我真的不确定是否必须在我的 cpp 文件中再次调用 static 并 +1 以获得有关返回 int&amp; 的额外知识。
【解决方案2】:

static 关键字只能在 class 声明中使用。方法实现应该省略static 声明:

int& Complex::getNumObjects(){
        return counter;
}

奇怪的是,你的静态成员变量已经遵循了这条规则;-)

【讨论】:

    【解决方案3】:

    你绝对必须跟踪析构函数和构造函数中的对象。此外,您真的希望您的计数器为 atomic,以便在多个线程上运行时不会发生竞争条件。

    struct Complex
    {
      Complex()
      { ++counter; }
    
      Complex(Complex const&other)
      : _real(other._real), _imag(other._imag)
      { ++counter; }
    
      Complex(double r, double i=0)
      : _real(r), _imag(i)
      { ++counter; }
    
      // and so on for all other constructors
    
      Complex&operator=(Complex const&) = default;
    
      Complex&operator=(double x)
      {
        _real = x;
        _imag = 0;
        return *this;
      }
    
     ~Complex() { --counter; }
    
      static int getNumObjects() { return counter; }
    
    private:
      double _real,_imag;
      static std::atomic<int> counter;
    };
    

    实际上并不需要移动构造函数(因为堆上没有数据由Complex 管理)。

    【讨论】:

      猜你喜欢
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 1970-01-01
      • 2016-02-09
      • 1970-01-01
      • 2011-09-30
      相关资源
      最近更新 更多