【问题标题】:Why would you use pointers in a class definition?为什么要在类定义中使用指针?
【发布时间】:2014-03-16 06:43:32
【问题描述】:

一开始我对指针的理解还很薄弱,但我没能找到在类定义中需要它们的确切原因。

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

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

class Circle : public Shape {

  private: int* radius;

  ....
  ....

}

为什么半径会是一个指针?这是为了什么目的?

【问题讨论】:

  • 你可以从类外更改radius指向的值。
  • 我必须假设剖析.... 的两行和后续实现,这两者你都可以使用,而我们都没有,可能会导致至少一个 关于作者意图的一些见解(包括他们被/被误导的潜在可能性)。正如现在所呈现的,您要求我们说出作者的想法,而纯粹的猜测是唯一可能的结果。 radius 的目的是指向某些东西(duh)。除此之外,如果不查看更多代码,就不可能说出为什么
  • 喜欢..个人喜好?
  • 如果您想不出使用指针的情况,请不要担心。当确实出现需要指针的情况时,您可以使用指针。 FWIW 我也看不出作者打算用radius 做什么。

标签: c++ class oop pointers


【解决方案1】:

指针的用例基于这样一个事实,即指针指向同一内存位置的两个对象可以通过该内存进行通信。

三个主要目的是:

  • 通信本身(参见下面的示例)
  • 经济:如果你的函数需要一些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);

现在您可以通过调用shared 变量的getValuesetValue 方法来获得c1c2 通信

【讨论】:

  • 我确定我必须阅读/查看一些教程才能更好地理解指针的使用,但这是一个绝对清晰简洁的解释,谢谢。
  • 指针本身就是引用,一般不需要通过引用传递。更严格地说,如果你的指针是 IN 参数,你可以按值传递它。如果您的指针是 OUT 参数(当您需要从单个调用中返回多个值时),那么您通过引用或双指针(例如 int**)传递它
  • 示例:void MethodWithSeveralOutput(const int *inputParam, int **output1, double **output2) { *output1 = inputParam; *输出2 =新双[1];输出2[0] = *输入参数; }
  • 我可以问你一个关于 SO 的禁止问题而不在这里被猛烈抨击吗?我来自 c# 和 Java 背景。指针的原因是什么?
  • 看看这个:stackoverflow.com/questions/22146094/…。原因是:在 Java 中,所有东西(除了原语)实际上都是一个指针。在 C# 中,所有东西(除了结构体和原语)实际上也是一个指针。
【解决方案2】:

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

在上面的示例中,将 radius 声明为指针似乎违反直觉(事实上,有人可能会争辩说这没有必要:它没有提供任何真正的好处,但却使程序员的事情变得复杂)。

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

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

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

附带说明,Person 类的代码绝对不是正确的 C++ 处理方式。使用std::string 将是可行的方法。

【讨论】:

    【解决方案3】:

    您通常会使用指针来引用 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 2019-11-01
      • 2010-09-14
      相关资源
      最近更新 更多