PC
和Printer
是来自基类Item
的派生类,如果我创建一个类型为Item
的指针数组,我想为数组分配内存根据用户的输入,它可以使数组中的元素为PC
s或Printer
s或混合使用。
所有错误都是一样的:
错误:类“Item”没有成员“getPC_Counter()”和“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;
}
答案 0 :(得分:0)
您需要使用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];
答案 1 :(得分: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;
答案 2 :(得分:0)
解决问题的常见模式称为双重调度 它遵循一个最小的工作示例:
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
或任何其他技术。
答案 3 :(得分:0)
问题不明确。也许它是:你为什么得到:
“错误:类”项目“没有成员”getPC_Counter()“和 “getP_Counter()”和“setCapacity()”和“setType()”
这些错误是不言自明的。您根本没有为基本类型“Item”编码这4种方法。
如果您要使用多态派生对象,即使用虚方法,则您的虚方法(基类)不应该关注哪种类型的派生。基类成为派生类的接口定义。
即。调用虚方法print()将调用派生类型的print()。
如果打印机具有PC不具备的方法(反之亦然),则有2种(或更多)方法可以解决基类(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 */ }
或许更好的方法需要比计算机课更多的英语语言能力。此方法要求您创建每个派生类可以支持的动词。
经典的例子可能是类动物,有衍生物种。并非所有物种都可以吠叫,但也许你想要考虑的所有物种都可以发声(),或者他们说话(),吃饭()或者另一端。
Dog :: vocalize(){bark();几乎可以支持Animal :: vocalize(); }, cat :: vocalize(){meow();树皮和喵喵是物种(或派生类)的具体方法。
我猜不出你的意思是打印机:: setCapacity()或pc :: setCapacity()。你需要定义它。然后提出一个更加“通用”的动词,即PC和打印机都支持。也许这些办公设备对象不应该解决这些问题。
查看您的多态教程。仔细计划您的对象。
如果您可以改进它,请更新您的问题。
答案 4 :(得分:0)
您可以统计或动态转换该指针以了解他是什么类型 例如:
`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