我首先对指针的理解非常薄弱,但是很难找到你在类定义中确切需要它们的原因。
我知道指针是一种指向另一个变量的内存地址的变量。这就是我真正的理解开始和结束的地方。
但是,我不可能在这个派生类的开头看到它们的用法:
class Circle : public Shape {
private: int* radius;
....
....
}
为什么radius会成为指针?这有什么用途?
答案 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
变量的c2
和shared
方法来获取getValue
和setValue
进行通信
答案 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;
}