我正在嘗試找到一種方法來創建一個通用的“汽車”類,其中的子類會多載父類的方法。隨后,我希望有一個用戶類,它具有“汽車”系列中的任何類作為成員。有沒有辦法實作所需的功能?謝謝!
下面的偽代碼顯示了我最初的嘗試,但編譯器顯然抱怨用戶想要一個 Car 物件,而不是 Toyota。
class Car
{
public:
Car();
void method1();
};
class Toyota : public Car
{
public:
Toyota();
void method1();
};
class Lada : public Car
{
public:
Lada();
void method1();
};
class User
{
public:
User();
Car car;
};
int main()
{
User user;
Toyota toyota;
user.car = toyota;
}
uj5u.com熱心網友回復:
有幾種方法可以實作這一點。一種方法是使用允許您使用運行時多型性的指標或參考。對 a 的指標或參考Car也可以指向派生自 的類的任何物件Car。然而,要獲得真正的多型性,您需要宣告方法virtual。另外你真的應該delcare一個virtual ~Car() = default解構式:
struct Car {
virtual ~Car() = default; // virtual destructor is important if you
// hold owning references or pointers that
// you want to use to destroy the object
// (like for example std::unique_ptr)
virtual void method1(); // declare this virtual if you want
// polymorphic behaviour on method1
};
struct Toyota : public Car {
void method1() override; // no need to declare this virtual because
// it is already virtual in base class.
// the 'override' would warn you if there was
// no 'virtual method1' in the base class
};
// ...
Toyota toyota;
Car& car_ref = toyota;
Car* car_ptr = &toyota;
car_ref.method1(); // calls Toyota::method1()
car_ptr->method1(); // calls Toyota::method1()
如果使用參考或指標,您應該記住它們是非擁有的。如果取消參考指標或參考,則必須確保所參考的物件存在。
Car& f() {
Toyota toyota;
Car& car_ref = toyota;
return car_ref; // badooomz: return of reference to toyota
// that is going to be destroyed at the end
// of scope. You do not want this
}
將所有權與指標耦合的一種簡單方法是使用std::unique_ptr:
std::unique_ptr<Car> f() {
auto toyota = std::make_unique<Toyota>();
return std::move(toyota);
}
實作目標的一種完全不同的方法是通過以下方式使用靜態多型性(或鴨子型別)std::variant:
struct Car {
void method1(); // no virtual functions needed
};
struct Toyota { // note: no inheritance here
void method1();
};
// ...
Toyota toyota;
// store a toyota in the variant
std::variant<Car, Toyota /*,...*/> car = toyota;
// call Toyota::method1()
std::visit([](auto&& car_like){ car_like.method1(); }, car);
請注意,在此示例中,Car和之間根本沒有任何關系。Toyota您可以將任何物件存盤在變體中,這obj.method1()是一個有效的函式呼叫。這就是為什么這種靜態多型被稱為鴨子型別——任何看起來像鴨子的東西都被當作鴨子對待。請注意,使用時std::variant您存盤物件的副本而不是變體中的參考。因此,即使原始物件在離開函式范圍時被破壞,從函式回傳變體也是安全的。
uj5u.com熱心網友回復:
派生到基類的轉換只能使用基類的指標或參考(Car在我們的示例中)。這意味著您需要將資料成員car設定為型別Car&或Car*如下所示:
class User
{
public:
//-----------vvvv---------------------->added this parameter
User(Car& pCar):car(pCar){}
//----------v-------------------------->make car a Car&
Car &car; //now we have a reference to the base class Car
};
int main()
{
Toyota toyota;
//-------------vvvvvv-------->pass as argument
User user(toyota);
}
此外,method如果您希望能夠使用動態系結,則應將成員函式設為虛擬。
演示
您還可以參考在 c 中是否可以在不使用指標和使用常規物件的情況下進行動態系結。
uj5u.com熱心網友回復:
我認為您應該在汽車內部使用虛函式和將豐田類分配給汽車的參考指標,我在下面撰寫的代碼運行良好。
#include <iostream>
using std::cout;
class Car
{
public:
Car(){cout << "A car";};
virtual void method1(){cout << "from car";};
};
class Toyota : public Car
{
public:
Toyota(){cout << "A toyota";};
void method1() {cout << "from toyota";};
};
class Lada : public Car
{
public:
Lada(){cout << "A Lada";};
void method1() {cout << "from lada";};
};
class User
{
public:
User(){cout << "A user";};
Car *car;
};
int main()
{
User *user = new User();
Toyota toyota;
user->car = &toyota;
/***
if you dont need pointers then
User user;
Toyota toyota;
user.car = &toyota;
/**
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/522377.html
標籤:C 班级目的哎呀
