[英]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
and Printer
are derived classes from the base class Item
, if I make an array of pointers of type Item
, and I wanna allocate memory for the array based on the user's input so it can make the elements in the array either PC
s or Printer
s or a mix of them. PC
和Printer
是基类Item
派生类,如果我创建一个Item
类型的指针数组,我想根据用户的输入为数组分配内存,这样它就可以使数组中的元素成为PC
或Printer
s或它们的混合。
all the errors are the same: 所有错误都是一样的:
ERROR: class "Item" has no member "getPC_Counter()" and "getP_Counter()" and "setCapacity()" and "setType()"
错误:类“Item”没有成员“getPC_Counter()”和“getP_Counter()”和“setCapacity()”和“setType()”
Sorry for asking my question in a very weird and complicated manner but i don't really know how to explain my question properly, any ways here's my code and i'll try to explain what i can't figure out in the comments: 很抱歉以非常奇怪和复杂的方式提出我的问题,但我真的不知道如何正确解释我的问题,这里的任何方式都是我的代码,我将尝试解释我在评论中无法弄清楚的内容:
#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;
}
You need to use dynamic_cast
to cast your base pointer down to the derived pointer you require. 您需要使用
dynamic_cast
将基指针向下转换为所需的派生指针。 For example, in the case of PC
: 例如,在
PC
的情况下:
dynamic_cast<PC*>(store[i])->setType(t);
will work, as this casts Item*
(the base) down to a PC*
(the derived). 将工作,因为这将
Item*
(基础)下放到PC*
(派生的)。
Note, as this is C++, you should really be using std::unique_ptr
and std::vector
instead of raw-pointers and C-style arrays, respectively. 注意,因为这是C ++,你应该分别使用
std::unique_ptr
和std::vector
而不是原始指针和C风格的数组。 The former will still allow dynamic casting and polymorphism. 前者仍然允许动态转换和多态。 In other words, use:
换句话说,使用:
std::vector<std::unique_ptr<Item>> store;
instead of 代替
Item* store[5];
I would say the correct way to do this is to make getP_Counter
and getPC_Counter
static member functions. 我想说这样做的正确方法是使
getP_Counter
和getPC_Counter
静态成员函数。 Then there is no requirement for dynamic dispatch, as those functions only access static data anyway. 然后不需要动态调度,因为这些函数无论如何只访问静态数据。
...
// 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';
To deal with setCapacity
and setType
simply delay erasing the type by initially assigning to the real type and add this to the array after calling those functions. 处理
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;
A common pattern to solve the issue is known as double dispatching. 解决该问题的常见模式称为双重调度。
It follows a minimal, working example: 它遵循一个最小的工作示例:
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);
}
The basic idea is that you can use a visitor class that is accepted by all of the classes that belong to your hierarchy. 基本思想是您可以使用属于您的层次结构的所有类都接受的访问者类。
When a class in the hierarchy accepts a visitor, it promotes itself to the right type and pass a reference to the visitor. 当层次结构中的某个类接受访问者时,它会将自己提升为正确的类型并将引用传递给访问者。
It's heavily based on polymorphism and pretty invasive as a solution, but it doesn't require you to use dynamic_cast
or any other technique. 它主要基于多态性和非常具有侵入性的解决方案,但它不要求您使用
dynamic_cast
或任何其他技术。
The Question is not clear. 问题不明确。 Perhaps it is: Why do you get:
也许它是:你为什么得到:
"ERROR: class "Item" has no member "getPC_Counter()" and "getP_Counter()" and "setCapacity()" and "setType()"
“错误:类”项“没有成员”getPC_Counter()“和”getP_Counter()“和”setCapacity()“和”setType()“
These errors are self explanatory. 这些错误是不言自明的。 You simply have not coded these 4 methods for the base type "Item".
您根本没有为基本类型“Item”编码这4种方法。
If you are headed for polymorphic derived objects, ie using virtual methods, your virtual methods (of base class) should not care which type of derived. 如果您正在寻找多态派生对象,即使用虚方法,那么您的虚方法(基类)不应该关注哪种派生类型。 The base class becomes an interface definition for the derived classes.
基类成为派生类的接口定义。
ie Invoking the virtual method print() will invoke the derived type's print(). 即调用虚方法print()将调用派生类型的print()。
If a printer has methods that a PC does not (or vice versa) there are 2 (or more) approaches to resolve this 'mis-match' between base class (Item) and the derived classes. 如果打印机具有PC不具备的方法(反之亦然),则有2种(或更多种)方法可以解决基类(Item)和派生类之间的“不匹配”问题。
I prefer to have base class methods for all possible derived methods. 我更喜欢为所有可能的派生方法提供基类方法。 So I would add the four methods to base class (all marked as virtual)
所以我会将这四种方法添加到基类(全部标记为虚拟)
Item::getPC_Counter()
Item::getP_Counter()
Item::setCapacity()
Item::setType()
I also prefer for the base class methods to handle (perhaps an error / warning message) the concept of asking a derived to perform a method that it does not support. 我也更喜欢基类方法来处理(可能是错误/警告消息)请求派生执行它不支持的方法的概念。 This lack of support is caused by 'mixing apples an oranges' in a polymorhpic effort.
这种缺乏支持是由于在多重努力中“混合苹果和橙子”。 (I've seen this quite often.)
(我经常看到这个。)
If setCapacity() is meaningless for derived class Foo, 如果setCapacity()对派生类Foo没有意义,
// virtual
Item::setCapacity(std::string lbl)
{ std::cerr << " invalid setCapacity() for " << lbl << std::endl; }
and 和
Foo::setCapacity() { Item::setCapacity("Foo"); }
See how the virtual method in Foo sent info up to the base class method? 看看Foo中的虚方法如何将信息发送到基类方法?
And for a derived class Bar, which does have a capacity to set: 对于派生类Bar,它具有设置容量:
Bar::setCapacity() { /* perform Bar requirements */ }
Perhaps a better approach requires more English language ability than is taught in computer class. 也许更好的方法需要比计算机课更多的英语语言能力。 This approach requires that you create a verb that each derived class can support.
此方法要求您创建每个派生类可以支持的动词。
The classic example is perhaps class animal, with derived species. 典型的例子可能是类动物,衍生物种。 Not all species can bark, but maybe all the ones you wish to consider can vocalize(), or perhaps they speak(), or eat() or, well the other end.
并非所有物种都可以吠叫,但也许你想要考虑的所有物种都可以发声(),或者他们说话(),吃饭()或者另一端。
Animal::vocalize() can be virtually supported by dog::vocalize() { bark(); Dog :: vocalize(){bark();几乎可以支持Animal :: vocalize(); }, cat::vocalize() { meow();
},cat :: vocalize(){meow(); }, where bark and meow are species (or derived class) specific methods.
其中树皮和喵喵是物种(或派生类)的具体方法。
I can not guess what you would mean by printer::setCapacity(), or pc::setCapacity(). 我猜不出你的意思是打印机:: setCapacity()或pc :: setCapacity()。 You need to define it.
你需要定义它。 And then come up with a more 'generic' verb that both pc and printer support.
然后提出一个更加“通用”的动词,即PC和打印机都支持。 And maybe these office equipment objects should not address these issues.
也许这些办公设备对象不应该解决这些问题。
Review your polymorphic tutorials. 查看您的多态教程。 Plan your objects carefully.
仔细计划您的对象。
Update your question when you can improve it. 如果您可以改进它,请更新您的问题。
You can statistically or dynamically cast that pointer to know what type he is example : 您可以统计或动态转换该指针以了解他的示例类型:
`auto e = dynamic_pointer_cast<Type>(pointer);`
dynamic cast are expensive thing and you probably want to use static_cast if u know what type is it 动态转换是昂贵的事情,你可能想要使用static_cast,如果你知道它是什么类型
auto e = static_pointer_cast<expecting type>(pointer);
example : 例如:
auto e = static_pointer_cast<Pc>(pointer);
also if u are using raw pointers you want to use static_cast instead of static_pointer_cast 如果你正在使用原始指针,你想使用static_cast而不是static_pointer_cast
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.