#include <iostream>
#include <string>
using namespace std;
class Part{
public:
std::string spec;
Part(std::string str){
this->spec = str;
}
std::string getSpec(){
return spec;
}
};
class Car{
public:
Part getEngine();
Part getWheels();
Part getBody();
};
class Benz:public Car{
public:
Part getEngine(){
return Part("Benz Engine");
}
Part getWheels(){
return Part("Benz Wheels");
}
Part getBody(){
return Part("Benz Body");
}
};
class Audi:public Car{
public:
Part getEngine(){
return Part("Audi Engine");
}
Part getWheels(){
return Part("Audi Wheels");
}
Part getBody(){
return Part("Audi Body");
}
};
class CarFactory{
public:
Car *pcar;
Car *getCar(std::string carType){
if (carType.compare("Benz") == 0){
pcar = new Benz();
}else if (carType.compare("Audi") == 0){
pcar = new Audi();
}
return pcar;
}
};
int main(){
CarFactory *cf = new CarFactory();
Car *mycar = cf->getCar("Benz");
Part myCarBody = mycar->getBody();
cout <<myCarBody.getSpec() <<endl;
//cout << mycar->getBody().getSpec() <<endl;
}
在上面的代码获取中,未定义引用对象错误的行部分myCarBody = mycar-&gt; getBody(); 主函数行。你能帮我解决这个问题吗?请解释 Car * mycar和Car mycar 之间的区别。选择哪一个?
感谢您的帮助。
答案 0 :(得分:6)
Car
的成员函数应该是纯虚拟,而不是非虚拟声明:
class Car
{
public:
virtual ~Car() = default; // Virtual destructor
virtual Part getEngine() = 0;
virtual Part getWheels() = 0;
virtual Part getBody() = 0;
};
这就是链接器错误的原因。 编译器需要Car
的函数定义,因为这些函数不是纯虚函数,但找不到它。
使用纯虚拟成员函数, Car
成为一个抽象类并提供一个接口(纯虚拟),必须通过从它派生的类来实现。否则,派生类也将是抽象的,不可实例化。
通过调用基类的虚函数,最终会调用覆盖它的派生类的函数。 析构函数也是如此,需要虚拟,以便调用派生类的析构函数并避免未定义的行为。如果在其中一个派生类中有动态分配的数据,则会出现内存泄漏。
此外,在处理多态时,你必须使用指针或引用。它背后的逻辑是指针具有相同的大小,但像Benz
这样的派生类可能有额外的数据,不适合Car
占用的空间,并会被切片。因此,没有指针或引用,赋值/复制构造就无法正常工作。
建议发表评论:
访问者功能(“getters”和“setters”)通常带有
私人或受保护的成员。你的是公共的,访问者是
没用,可以规避。保留访问者,制作数据
私人的。当你返回一个成员时,你可以通过
引用给const。但不要为getEngine
,getWheels
和getBody
执行此操作
std::string const& getSpec() { return spec; }
,因为他们返回的是本地对象,而不是成员。
std::string
虽然我们正在使用它,但您也可以通过引用传递给Part(std::string const& str) : spec(str) {}
。
class CarFactory
{
public:
Car *getCar(std::string const& carType)
{
if(carType == "Benz") // std::string::compare is for comparing by alphabetical order
return new Benz();
if(carType == "Audi")
return new Audi();
return nullptr; // invalid carType, return nullptr and check for that in main()
// You were returning previously constructed Car, was that desired?
}
};
工厂类
myCar
您还忘记删除<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" >
<ImageView
android:id="@+id/uivProfileImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:adjustViewBounds="true"
android:contentDescription="@null"
android:maxHeight="100dp"
android:maxWidth="100dp"
android:scaleType="fitXY" />
<ImageView
android:id="@+id/uivProfileCoverImage"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_toRightOf="@+id/uivProfileImage"
android:adjustViewBounds="true"
android:contentDescription="@null"
android:maxHeight="100dp"
android:scaleType="fitXY" />
</RelativeLayout>
,请在其他答案中查看更多有关信息。
答案 1 :(得分:5)
首先,如果您想使用polymorphism,则需要将函数声明为virtual。
如果您不打算在基类中实现方法,可以将它们声明为pure virtual。这使你的基类所谓的&#34; abstract&#34;并且您将无法创建该类的对象(在您的示例中,最佳候选者是Car对象)。
还要小心。如果要通过指向基类的指针销毁对象,还需要virtual destructor。
所以你需要把所有东西放在一起:
class Car {
public:
virtual ~Car() {}
virtual Part getEngine() = 0;
virtual Part getWheels() = 0;
virtual Part getBody() = 0;
};
因此,你对编译器说的问题的根本原因&#34;嘿,我将实施Car&#34;的方法。但还没有完成。所以编译器期望从你的main调用那些方法,但在linking阶段链接器上找不到它们。
您需要考虑的另一个问题: