打印出存储在具有相同祖先的不同类的变量中的值
Print out the values stored in vars of different classes, that have the same ancestor
我有这个类:
class CComputer {
public:
// constructor
CComputer(string name) {
this->name = name;
};
// overloaded operator << for printing
friend ostream& operator<<(ostream& os, const CComputer& c);
// adds some component for this computer
CComputer & AddComponent(Component const & component) {
this->listOfComponents.push_back(component);
return *this;
};
// sets address for this computer
CComputer & AddAddress(const string & address) {
this->address = address;
return *this;
};
string name;
string address;
list<Component> listOfComponents;
};
然后是这些类:
// ancestor for other classes...It's really dummy yet, but I dunno what to add there
class Component {
public:
Component() {};
~Component() {};
};
class CCPU : public Component {
public:
CCPU(int cores, int freq) {
this->cores = cores;
this->freq = freq;
};
int cores;
int freq;
};
class CMemory : public Component {
public:
CMemory(int mem) {
this->mem = mem;
};
int mem;
};
现在我给我的CComputer类提供一些值:
CComputer c("test.com");
c . AddAddress("123.45.678.910") .
AddComponent(CCPU(8, 2400)) .
AddComponent(CCPU(8, 1200)).
AddComponent(CMemory(2000)).
AddComponent(CMemory(2000)));
现在我想把我放在那里的所有信息打印出来(包括CCPU
和CMemory
的详细信息(
但是如何实现它,能够在CComputer::listOfComponents
中迭代,而不在乎我是实际访问CCPU
还是CMemory
?我可以将它添加到该列表中,但我真的不知道如何创建它,以便能够访问这些组件的变量。
所以输出应该看起来像:
##### STARTING #####
CComputer:
name:test.com
address:123.45.678.910
CCPU:
cores:8,freq:2400
CCPU:
cores:8, freq:1200
CMemory:
mem:2000
CMemory:
mem:2000
###### FINISHED! #####
正如其他人所提到的,您需要在基类中实现一个由每个子类继承和重写的虚拟函数(例如virtual std::string ToString() const = 0;
(。
然而,这还不够。您的代码展示了当您将子类实例复制到列表中时发生的切片:列表包含类型为Component
的对象,而不是相关子类的对象。
您需要做的是存储多态实例。值本身从来都不是多态的,您需要为此使用(智能(指针或引用。但是,引用是不存在的,因为不能将它们存储在标准容器(如std::list
(中。现在,使用原始指针被认为是一种糟糕的风格,但从类的命名约定来看,你在类中没有学习到现代C++(对不起!(。
因此,原始指针可能是最好的选择。相应地更改您的代码:
-
存储指针列表:
list<Component*> listOfComponents;
-
将
AddComponent
的参数类型设置为指针,而不是const&
。 -
通过传递
new
ed对象来调用函数,例如:AddComponent(new CCPU(8, 2400))
现在,您的代码向左、向右和居中泄漏内存。你需要实现一个析构函数来释放内存:
~CComputer() {
typedef std::list<Component*>::iterator iter_t;
for (iter_t i = listOfComponents.begin(); i != listOfComponents.end(); ++i)
delete *i;
}
但是现在你的代码违反了三条规则(阅读这篇文章!这很重要,这可能是你将在这个编程类中学习的C++最有用的东西(,因此你还需要实现复制构造函数和复制赋值运算符。然而,我们不能。很抱歉为了实现类的复制,您必须在Component
类中实现另一个虚拟函数,即克隆对象(virtual Component* Clone() const = 0;
(的函数。只有然后才能继续。
以下是CCPU
中的示例实现:
Component* Clone() const {
return new CCPU(cores, freq);
}
…这需要在从Component
派生的所有类中完成,否则我们无法正确复制从Component
派生并隐藏在指针后面的类型的对象。
现在我们可以在CComputer
类中实现复制:
CComputer(CComputer const& other)
: name(name)
, address(addess) {
typedef std::list<Component*>::iterator iter_t;
for (iter_t i = other.listOfComponents.begin(); i != other.listOfComponents.end(); ++i)
listOfComponents.push_back((*i)->Clone());
}
CComputer& operator =(CComputer const& other) {
if (this == &other)
return *this;
name = other.name;
address = other.address;
listOfComponents.clear();
for (iter_t i = other.listOfComponents.begin(); i != other.listOfComponents.end(); ++i)
listOfComponents.push_back((*i)->Clone());
return *this;
}
这段代码很脆弱,不是线程安全的,而且很容易出错,没有一个称职的C++程序员会写这1Real代码会使用智能指针,但正如前面提到的,我确信这超出了类的范围。
1我想知道这让我现在怎么样了?
只需向class Component添加一个名为toString((的虚拟方法,该方法将返回一个描述组件的字符串。然后你可以遍历所有组件并调用toString((,而不用担心每个组件到底是什么。如果你这样做,那么对于每台计算机,你就可以打印出所有组件的值。
然而,正如其中一条评论中所指出的,您在问题中给出的示例输出输出了所有计算机的CCPU,然后是所有计算机的所有内存。要对输出进行这样的排序,您需要向Component添加另一个名为getType((的虚拟方法,该方法返回表示信息类型的枚举或整数。然后,您可以有两个for next循环,一个嵌套在另一个循环中,其中外部循环遍历所有类型,内部循环遍历所有计算机,调用与外部for循环中指定的类型匹配的所有组件上的toString((。
以下是实现这个想法的东西。
#include <iostream>
#include <string>
#include <list>
using namespace std;
int const TYPE_CCPU = 1;
int const TYPE_MEMORY = 2;
class Component {
public:
virtual int GetType() { return -1; }
virtual std::string ToString() const {
return "OOPS! Default `ToString` called";
}
};
class CComputer {
public:
typedef std::list<Component*>::iterator iter_t;
// constructor
CComputer(string name) {
this->name = name;
};
~CComputer() {
for (iter_t i = listOfComponents.begin(); i != listOfComponents.end(); ++i) {
delete *i;
}
}
// overloaded operator << for printing
friend ostream& operator<<(ostream& os, const CComputer& c);
// adds some component for this computer
CComputer & AddComponent(Component *component) {
this->listOfComponents.push_back(component);
return *this;
};
// sets address for this computer
CComputer & AddAddress(const string & address) {
this->address = address;
return *this;
};
void PrintType(int type) {
for (iter_t i = listOfComponents.begin(); i != listOfComponents.end(); ++i) {
if ((*i)->GetType() == type)
std::cout << (*i)->ToString() << 'n';
}
}
string name;
string address;
list<Component*> listOfComponents;
};
class CCPU : public Component {
public:
CCPU(int cores, int freq) {
this->cores = cores;
this->freq = freq;
};
int GetType() { return TYPE_CCPU; }
std::string ToString() const {
return "CCPU::ToString()";
}
int cores;
int freq;
};
class CMemory : public Component {
public:
CMemory(int mem) { this->mem = mem; };
int GetType() { return TYPE_MEMORY; }
std::string ToString() const {
return "CMemory::ToString()";
}
int mem;
};
typedef std::list<CComputer*>::iterator iter_c;
int main() {
list<CComputer*> computerlist;
CComputer *c1 = new CComputer("test.com"), *c2 = new CComputer("test2.com");
c1->AddAddress("123.45.678.910").
AddComponent(new CCPU(8, 1200)).
AddComponent(new CMemory(2000));
computerlist.push_back(c1);
c2->AddAddress("987.65.432.10").
AddComponent(new CCPU(8, 2400)).
AddComponent(new CMemory(4000));
computerlist.push_back(c2);
for(int t=TYPE_CCPU; t<=TYPE_MEMORY; t++)
for (iter_c i = computerlist.begin(); i != computerlist.end(); ++i) {
(*i)->PrintType(t);
}
for (iter_c i = computerlist.begin(); i != computerlist.end(); ++i) {
delete (*i);
}
}
在每个类中实现ToString((。在.NET中,这是一个标准,即使是"对象"类型也能实现。
- 对具有相同方法的不同类使用一个变量
- 在C++/虚幻引擎4中访问不同类中的静态变量
- 在不同类的对象之间共享变量 (C++)
- 如何将具有不同类(但相同基础)的对象存储在一个变量中
- 类和变量声明(相同类类型)
- C++-从不同的类中获取不同类中的变量集
- 创建可以包含不同类的变量
- 将变量指向来自不同类类型的成员函数
- 如何访问不同类的变量
- 是否可能有一个变量是对具有不同类标识符的模板类的引用?
- C++使用来自不同类的公共变量
- 具有相同类名的变量
- c++更新/更改来自不同类/变量的变量
- 如何在c++中访问定义在不同类中的变量
- 打印出存储在具有相同祖先的不同类的变量中的值
- 多线程——在不同类的方法之间传递变量
- 获取访问不同类中的顶级变量和方法
- 不同类中同名全局变量的双重初始化
- 如何处理来自不同类的私有变量
- 存储对具有不同类的对象成员变量的引用