[英]Default value for abstract class pointer parameter
我正在嘗試做這樣的事情:
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print();
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(), second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
我們如何設置抽象類指針的默認值以及如何將它們作為參數從 main 傳遞?
我還希望能夠像這樣只在一行中傳遞來自 main 的參數,而無需事先初始化。
任何人都可以幫我解決我們如何在 C++ 中做這些事情嗎?
我已經嘗試並搜索了很多但沒有運氣。
我正在尋找一種解決方法來做這樣的事情,其中我們使用抽象類作為其他類的參數。
我知道對象不能分配給指針,我只是不知道在那里做什么來滿足我的要求,一個抽象類作為具有默認值的參數。
這是我使用精確代碼的最新嘗試,但不幸的是,使用new
,有沒有人知道如何擺脫new
並達到預期的結果?
筆記:
我的實際代碼非常復雜,基本上使用抽象類進行多態,並將這些抽象類作為參數傳遞給具有默認參數的另一個類,如果有任何其他方法可以做類似的事情,我將非常感謝您的幫助。
這確實是一個設計問題。 在Model
類設計中,您要么需要決定對象所有權,要么將決定推遲到調用代碼。 在后一種情況下,你不能有默認參數(除非你想要全局常量Human
和Walk
,但我不推薦它)。
使用默認參數的一種方法是決定Model
擁有Animal
和Movement
獨占所有權,並將unique_ptr
存儲到它們。 像這樣的東西:
class Model {
unique_ptr<Animal> animal;
unique_ptr<Movement> movement;
public:
Model(unique_ptr<Animal> animal = make_unique<Human>(), unique_ptr<Movement> movement = make_unique<Walk>()){
this->animal = std::move(animal);
this->movement = std::move(movement);
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first/*no () here!*/, second(make_unique<Lion>(), make_unique<Run>());
first.print();
cout << endl;
second.print();
return 0;
}
我想我想出了最適合我的情況的解決方案。
#include <iostream>
#include <memory>
using namespace std;
class Movement {
public:
virtual void move() = 0;
virtual unique_ptr<Movement> movement() const = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
unique_ptr<Movement> movement() const { return make_unique<Walk>(); }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
unique_ptr<Movement> movement() const { return make_unique<Run>(); }
};
class Animal {
public:
virtual void print() = 0;
virtual unique_ptr<Animal> animal() const = 0;
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
unique_ptr<Animal> animal() const { return make_unique<Human>(); }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
unique_ptr<Animal> animal() const { return make_unique<Lion>(); }
};
class Model {
unique_ptr<Animal> animal;
unique_ptr<Movement> movement;
public:
Model(const Animal& animal = Human(), const Movement& movement = Walk()) {
this->animal = animal.animal();
this->movement = movement.movement();
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(), second = Model(Lion(), Run());
first.print();
cout << endl;
second.print();
return 0;
}
你的問題是編譯錯誤嗎? 有多種方法可以解決編譯錯誤,但鑒於您的問題是關於從抽象類繼承,我將重點關注這一點。
首先,正如所提供的,您的Animal
類不是抽象類。 抽象類不能被實例化,因為它的所有方法都是純虛擬的。 在 C++ 中,純虛函數由virtual
關鍵字前綴指定,並在其定義中以= 0
為后綴。 例如
...
virtual void print() = 0;
...
通過使您的Animal
類成為抽象類,可以編譯以下代碼:
#include <iostream>
using namespace std;
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print() = 0;
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(),
second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
順便說一句,您的代碼也可以通過提供Animal::print()
的實現來進行編譯。 以下代碼也是可編譯的,但Animal
不是抽象類,因為它提供了Animal::print()
的實現,而不是使用= 0
后綴:
#include <iostream>
using namespace std;
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print() {};
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(),
second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
否則,從概念上講,您在 C++ 中所做的一切都很好並且完全可能:將默認值分配給某個函數參數列表中的基類指針。
重要提示:正如評論者正確指出的那樣,您編碼的模式是危險的:您的界面是這樣的,用戶可以選擇提供一個Animal
實例。 問題是:如果Model
創建者這樣做了,那么可以合理地論證他正確地擁有該對象。 如果他不這樣做,那么您的構造函數將創建一個新的Animal
實例,但Model
既不獲取對象的所有權,也不提供用戶可以獲取新Animal
實例所有權的接口。 因此,這會造成內存泄漏。 同樣,代碼風險是Model
構造函數中使用的Animal
實例的所有權不明確。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.