在 c++ 中,如何从对象获取到静态成员
In c++, how can I get from an object to a static member?
所以我有以下问题:
假设我有一个名为 Shape 的基类,声明如下:
class Shape
{
public:
virtual void output(std::ostream &) const = 0;
}
形状派生了一些类,比如矩形和三角形。 这些类具有一个名为 identifier 的静态成员,如以下示例所示:
class Rectangle: public Shape
{
public:
static const std::string identifier;
}
现在还有另一个类,它实现了指向形状命名组的指针向量
class Group : public Shape
{
private:
std::vector<Shape *> continut;
public:
static const std::string identifier;
void output(std::ostream &) const;
}
现在我的问题是我如何为组实现读写。
我已经为三角形和矩形实现了>>和<<运算符,我想到的想法是使用标识符来确定对象类型,问题是标识符是静态的,所以我想知道在这种情况下我可以做到。
欢迎任何帮助。谢谢。
通常,如果要执行动态调度的操作,则必须使用虚函数。
class Shape
{
virtual ~Shape() {} //ALWAYS HAVE THIS IF YOU HAVE VIRTUAL FUNCTIONS
virtual void read(std::istream&) =0;
virtual void write(std::ostream&) const =0;
public:
virtual void output(std::ostream &) const = 0;
friend std::istream& operator>>(std::istream& in, Shape& sh)
{sh->read(in); return in;}
friend std::ostream& operator<<(std::ostream& out, const Shape& sh)
{sh->write(out); return out;}
};
class Rectangle: public Shape
{
virtual void read(std::istream&);
virtual void write(std::ostream&);
public:
static const std::string identifier;
//does not need (and probably should not have) `operator>>` and `operator<<`.
};
class Group : public Shape
{
virtual void read(std::istream&);
virtual void write(std::ostream&);
private:
std::vector<Shape*> continut;
public:
static const std::string identifier;
void output(std::ostream &) const;
//does not need (and probably should not have) `operator>>` and `operator<<`.
}
然后在实现中:
void Group::write(std::ostream& out)
{
//simply calls write for each shape with no separator
//you might want a separator
for(Shape* p : continut)
p->write(out);
}
void Group::read(std::istream& in)
{
//read is far more complicated
//but without knowing the IO format, I can't really help you much.
}
如果你想要一个简单的实现,也许像这样?
void Group::read(std::istream& in)
{
std::string shapename;
while(in >> shapename)
{
Shape* newshape = null;
if (in == "triangle")
newshape = new triangle();
else if (in == "square")
newshape = new square();
else if (in == "rectangle")
newshape = new rectangle();
else
throw std::runtime_error(in + " is not a known shape!");
newshape->read(in);
continut.push_back(newshape);
}
}
如果你想要一个更具可扩展性的答案,那么需要进行一些调整。
class Shape
{
virtual ~Shape() {} //ALWAYS HAVE THIS IF YOU HAVE VIRTUAL FUNCTIONS
virtual void read(std::istream&) =0;
virtual void write(std::ostream&) const =0;
//this stores functionoids that create the different shape types
typedef std::function<shape*(std::istream&)> named_ctor;
std::unordered_map<std::string, named_ctor> virtual_constructors;
public:
bool register_type(std::string name, named_ctor func)
{constructors[std::move(name)] = std::move(func); return true;}
virtual void output(std::ostream &) const = 0;
friend std::istream& operator>>(std::istream& in, Shape& sh)
{sh->read(in); return in;}
friend std::ostream& operator<<(std::ostream& out, const Shape& sh)
{sh->write(out); return out;}
};
class Rectangle: public Shape
{
virtual void read(std::istream&);
virtual void write(std::ostream&);
static shape* from_stream(std::ostream& in) {
shape s = new Rectangle();
s->read(in);
return s;
};
static const bool registered = register("Rectangle", from_stream);
public:
static const std::string identifier;
//does not need (and probably should not have) `operator>>` and `operator<<`.
};
class Group : public Shape
{
virtual void read(std::istream&);
virtual void write(std::ostream&);
static shape* from_stream(std::ostream& in) {
shape s = new Group();
s->read(in);
return s;
};
static const bool registered = register("Group", from_stream);
std::vector<Shape*> continut;
public:
static const std::string identifier;
void output(std::ostream &) const;
//does not need (and probably should not have) `operator>>` and `operator<<`.
}
然后实现成为
void Group::read(std::istream& in)
{
std::string shapename;
std::vector<Shape*> temp;
while(in >> shapename)
{
auto it = virtual_constructors.find(shapename);
if (it == virtual_constructors.end())
throw std::runtime_error(in + " is not a known shape!");
named_ctor& ctor = it->second;
Shape* newshape = ctor(in);
temp.push_back(newshape);
}
continuit = std::move(temp); //one step closer toward exception safety
}
如果我
理解正确,您的目标是在只有指向基类的指针并且不知道它是哪个派生类时读取派生类的静态成员。
这可以通过添加虚拟函数来访问该成员来解决。也就是说,在Shape
中添加:
virtual std::string getID() const = 0;
并在每个形状中添加
virtual std::string getID() const { return identifier; }
然后你可以得到这样的标识符
std::string id = continut[0]->getID();
相关文章:
- 如何在C++中获取该对象的类声明中对象的地址?
- 无法获取webot::PositionSensor对象中位置传感器的值
- 最多获取2个对象
- 从 Boost ASIO 获取 epoll 描述符 io_service对象
- 如何在新的派生对象中获取基本对象的数据?
- 如何从 CSV 获取数据并将其存储在 C++ 中的表对象中
- 数组中不同类型的对象并获取每个对象的类型
- push_back通过自行创建的对象获取最后一个元素的向量
- 我可以从列表中获取对象并复制它们,但如何删除我复制的对象?
- 在C++中从内部类对象获取外部类对象
- 如何从 GDI+ 图元文件对象获取原始图元文件字节
- C++ std::队列推送弹出两个不同的对象获取第一个对象
- 尝试从另一个类对象获取值时出现分段错误
- 从元对象获取属性更改通知程序
- 从 Json 对象获取非缩进字符串
- 从套接字对象获取fd或句柄
- (如何)我可以从IWbemClassObject对象获取GUID吗
- 使用不同类中的类对象获取不正确的数据
- OpenCV Mat 对象 - 获取数据长度
- 在 c++ 中,如何从对象获取到静态成员