为什么要在类定义中使用指针?

时间:2014-03-16 06:43:33

标签: c++ class oop pointers

我首先对指针的理解非常薄弱,但是很难找到你在类定义中确切需要它们的原因。

我知道指针是一种指向另一个变量的内存地址的变量。这就是我真正的理解开始和结束的地方。

但是,我不可能在这个派生类的开头看到它们的用法:

class Circle : public Shape {

  private: int* radius;

  ....
  ....

}

为什么radius会成为指针?这有什么用途?

3 个答案:

答案 0 :(得分:3)

指针'用例基于以下事实:指针指向相同内存位置的两个对象可以通过该内存进行通信。

三个主要目的是:

  • 沟通本身(见下面的例子)
  • 经济:如果您的函数需要一些BigFatObject作为参数,那么您将此参数声明为类型BigFatObject*。这样就可以将堆栈使用量从sizeof(BigFatObject)(可能很大)减少到sizeof(void*)(通常只有4/8字节)
  • 将更大的万能对象分解为更简单的对象的图形。在这种情况下,需要其他对象完成工作的对象将保存指向所需对象的指针

例如:

class SharedObject
{
public:
  int getValue() { return value; }
  void setValue(int value) { this->value = value; }  

private:
    int value;
};

class CommunicatesThroughSharedObject
{
public:
    CommunicatesThroughSharedObject(SharedObject *shared)
    {
        this->shared = shared;
    }

private:
    SharedObject *shared;
};

SharedObject shared;
CommunicatesThroughSharedObject c1(&shared), c2(&shared);

现在,您可以通过调用c1变量的c2shared方法来获取getValuesetValue进行通信

答案 1 :(得分:1)

指针允许您利用许多漂亮的语言功能,多态性和动态内存分配是我头脑中最重要的。其他一些技术,如pImpl成语也使用指针。

在上面的例子中,radius作为指针的声明似乎是反直觉的(事实上,人们可以说它没有必要:它没有提供任何实际的好处,但却使程序员的事情变得复杂)

但是,有些情况下指针作为成员非常有用。考虑以下情况,其中表示Person的类:

class Person
{
  char* _name;
  public:
      Person(const char* name);
};

现在,将成员name声明为指针允许您稍后分配内存,因此您只能通过ctor分配所需的内存。您可以使用数组执行相同的操作,但最终会浪费内存。

作为旁注,Person类的代码绝对不是正确的C ++处理方式。使用std::string将是最佳选择。

答案 2 :(得分:0)

您通常会使用指针来引用Class不拥有的资源,也许它与其他圈子共享。指针也可用于多态性。指针可以指向基类,并且直到运行时才确定实际类型。所有这些都可以使用引用更安全地实现,但指针具有可空的优点,因此如果资源可能不存在于构造Circle的位置,则可以使用它。

这对于半径来说没有多大意义,但可能对于记录器来说:

#include <iostream>
#include <string>

class Logger {
public:
  virtual ~Logger() {}
  virtual void log(const std::string& message) = 0;
};

class FileLogger : public Logger {
public:  
  void log(const std::string& message) {/*...*/ }

};

class TestLogger : public Logger {
public:
  void log(const std::string& message) { std::cout << message << std::endl;}
};

class Shape {
//...   
};

class Circle : public Shape {
private:
  int    radius;
  Logger* logger;
  //...
public:
  Circle() : radius(1), logger(nullptr) {}

  void setLogger(Logger* in) {logger = in;}

  void doSomething() {
    //...
    if (logger != nullptr)
      logger->log("Did something");
  }
};

int main() {
  Circle circle;
  circle.doSomething();
  TestLogger logger;
  circle.setLogger(&logger);
  circle.doSomething();
  return 0;
}