我怎么知道基类对象的指针数组中元素的类型,它将为派生类分配内存
how do i know what is the type of an element in an array of pointers to an object of base class, that will allocate memory for derived classes
PC
和Printer
是基类Item
的派生类,如果我制作一个类型为Item
的指针数组,并且我想根据用户的输入为数组分配内存,这样它就可以使数组中的元素成为PC
s或Printer
s或它们的混合。
所有的错误都是一样的:
错误:类"Item"没有成员"getPC_Counter()"answers"getP_Counter()"以及"setCapacity())和"setType()">
很抱歉以一种非常奇怪和复杂的方式问我的问题,但我真的不知道如何正确解释我的问题。无论如何,这是我的代码,我会尽力解释我在评论中无法理解的内容:
#include<iostream>
#include<string>
using namespace std;
class Item {
int ID;
public:
Item() {
ID = 0;
}
Item(int i) {
ID = i;
}
void print() {
cout << ID << endl;
}
int getID() {
return ID;
}
};
class PC :public Item {
static int PCc;
string type;
public:
PC() {
type = "";
PCc++;
}
void setType(string t) {
type = t;
}
void print() {
Item::print();
cout << type << endl;
}
string getType() {
return type;
}
int getPC_Counter() {
return PCc;
}
};
class Printer: public Item {
int capacity;
static int printerc;
public:
Printer() {
capacity = 0;
printerc++;
}
void setCapacity(int c) {
capacity = c;
}
void print() {
Item::print();
cout << capacity << endl;
}
int getCapacity() {
return capacity;
}
int getP_Counter() {
return printerc;
}
};
int PC::PCc = 0;
int Printer::printerc = 0;
int main() {
Item *store[5];
string c, t;
int cap;
cout << "pc or printer?" << endl;
for (int i = 0; i < 5; i++) {
cin >> c;
if (c == "pc") {
store[i] = new PC();
cout << "type?" << endl;
cin >> t;
//here how do i use the current element as an object of type PC?
store[i]->setType(t);
}
if (c == "printer") {
store[i] = new Printer();
cout << "capacity?" << endl;
cin >> cap;
//here how do i use the current element as an object of type Printer?
store[i]->setCapacity(cap);
}
}
//here how do i know if the element is of type printer or pc ?
//how do i use the getP_counter() and getPC_Counter funcions properly?
cout << "number of printers: " << store[0]->getP_Counter() << endl;
cout << "number of PCs: " << store[0]->getPC_Counter() << endl;
return 0;
}
我认为正确的方法是使getP_Counter
和getPC_Counter
成为静态成员函数。那么就不需要动态调度了,因为这些函数无论如何都只访问静态数据。
...
// make functions static
static int getPC_Counter() {
return PCc;
}
...
//later call static functions
cout << "number of printers: " << Printer::getP_Counter() << 'n';
cout << "number of PCs: " << PC::getPC_Counter() << 'n';
要处理setCapacity
和setType
,只需通过最初分配给实数类型来延迟擦除类型,并在调用这些函数后将其添加到数组中。
PC* pc = new PC();
cout << "type?" << 'n';
cin >> t;
//here how do i use the current element as an object of type PC?
pc->setType(t);
store[i] = pc;
您需要使用dynamic_cast
将基指针向下投射到所需的派生指针。例如,在PC
:的情况下
dynamic_cast<PC*>(store[i])->setType(t);
将起作用,因为这将Item*
(基础)向下转换为PC*
(派生)。
注意,因为这是C++,所以应该分别使用std::unique_ptr
和std::vector
,而不是原始指针和C样式数组。前者仍然允许动态铸造和多态性。换句话说,使用:
std::vector<std::unique_ptr<Item>> store;
而不是
Item* store[5];
解决该问题的一种常见模式称为双重调度
它遵循一个最小的工作示例:
struct Visitor;
struct Base {
virtual void accept(Visitor &) = 0;
};
struct Derived1: Base {
void accept(Visitor &v) override;
void f() {}
};
struct Derived2: Base {
void accept(Visitor &v) override;
void g() {}
};
struct Visitor {
void visit(Derived1 d) { d.f(); }
void visit(Derived2 d) { d.g(); }
};
void Derived1::accept(Visitor &v) { v.visit(*this); }
void Derived2::accept(Visitor &v) { v.visit(*this); }
void func(Base &b) {
Visitor v;
b.accept(v);
}
int main() {
Derived1 d1;
Derived2 d2;
func(d1);
func(d2);
}
基本思想是,您可以使用一个访问者类,该类被属于您的层次结构的所有类接受
当层次结构中的类接受访问者时,它会将自己提升为正确的类型,并将引用传递给访问者。
它在很大程度上是基于多态性的,并且作为一种解决方案非常具有侵入性,但它不需要使用dynamic_cast
或任何其他技术。
问题不清楚。也许是:你为什么得到:
"错误:类"Item"没有成员"getPC_Counter()"并且"getP_Counter()"answers"setCapacity())"以及"setType()">
这些错误不言自明。您只是没有为基本类型"Item"编码这4种方法。
如果您正在寻找多态派生对象,即使用虚拟方法,则您的(基类的)虚拟方法不应关心派生的类型。基类成为派生类的接口定义。
即调用虚拟方法print()将调用派生类型的print()。
如果打印机有PC没有的方法(反之亦然),有两种(或多种)方法可以解决基类(Item)和派生类之间的"不匹配"问题。
我更喜欢为所有可能的派生方法提供基类方法。所以我会将这四个方法添加到基类(都标记为虚拟)中
Item::getPC_Counter()
Item::getP_Counter()
Item::setCapacity()
Item::setType()
我也更喜欢基类方法来处理(可能是错误/警告消息)要求派生执行它不支持的方法的概念。这种缺乏支持的情况是由"把苹果和橙子混合在一起"造成的。(我经常看到这种情况。)
如果setCapacity()对于派生类Foo没有意义,则
// virtual
Item::setCapacity(std::string lbl)
{ std::cerr << " invalid setCapacity() for " << lbl << std::endl; }
和
Foo::setCapacity() { Item::setCapacity("Foo"); }
看看Foo中的虚拟方法是如何将信息发送到基类方法的?
对于派生类Bar,它确实有设置的能力:
Bar::setCapacity() { /* perform Bar requirements */ }
也许更好的方法需要比计算机课上更多的英语能力。这种方法要求您创建一个每个派生类都可以支持的动词。
典型的例子可能是类动物,以及衍生物种。并不是所有的物种都会吠叫,但也许你想考虑的所有物种都会发声(),或者它们会说(),或吃(),好吧,另一端。
动物::vocalize()实际上可以由狗::vocal(){bark();}支持,cat::vocalize(){meow();},其中树皮和meow是特定于物种(或派生类)的方法。
我猜不出你说的printer::setCapacity()或pc::setCapability()是什么意思。你需要定义它,然后想出一个pc和打印机都支持的更"通用"的动词。也许这些办公设备不应该解决这些问题。
查看您的多态教程。仔细规划你的物品。
当你可以改进的时候更新你的问题。
您可以统计或动态地投射该指针以了解其类型示例:
`auto e = dynamic_pointer_cast<Type>(pointer);`
动态转换是昂贵的东西,如果你知道是什么类型的,你可能想使用static_cast
auto e = static_pointer_cast<expecting type>(pointer);
示例:
auto e = static_pointer_cast<Pc>(pointer);
此外,如果您使用的是原始指针,您希望使用static_cast而不是static_pointer_cast
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 在C++中,为什么仅包含与其基类实例的联合的派生类占用的内存多于联合的大小?
- 由于从 std::map 派生的类中的 std::map 迭代器导致的内存错误
- 从 Qt 类派生的用户定义类中的内存所有权
- 删除派生类后,基本内存仍可访问
- 使用派生类分配基类指针的内存
- 我怎么知道基类对象的指针数组中元素的类型,它将为派生类分配内存
- 是否可以从现有基类动态分配派生类所需的额外内存
- 基本指针如何能够在派生的类实例中了解基本成员的内存位置
- 我如何处理成员的所有派生动态内存
- C++类及其派生类的内存池
- 将内存分配给基类的对象时,是否也分配了派生类的内存
- 基础类指针使用已分配的内存来派生类指针
- 派生类的实例化是否为基类的私有成员分配内存
- 派生类内存泄漏
- 如何使用malloc通过基类的指针为派生类的对象分配内存
- 在不增加类内存的情况下,我可以为派生类中基类的成员别名吗
- 派生类是否为成员变量分配内存
- 如何读取指向派生类的基类指针数组的内存布局
- 在cbasevideorenderer派生类中内存损坏