abstract class 指针参数的默认值
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;
}
我们如何设置抽象 class 指针的默认值以及如何像从 main 那样将它们作为参数传递?
我也希望能够像这样仅在一行中传递来自 main 的参数,而无需之前进行初始化。
任何人都可以帮助我在 C++ 中如何做这些事情吗?
我已经尝试和搜索了很多但没有运气。
我正在寻找一种解决方法来做这样的事情,其中我们使用抽象 classes 作为其他 classes 的参数。
我知道不能将对象分配给指针,我只是不知道该怎么做才能满足我的要求,抽象 class 作为具有默认值的参数。
这是我对精确代码的最新尝试,但不幸的是 new
,有谁知道如何摆脱 new
并达到预期的结果?
注:
我的实际代码相当复杂,基本上使用抽象 class 进行多态性并将这些抽象 class 作为参数传递给另一个具有默认参数的 class ,如果有 ANY 其他方式来做类似的事情我真的很感激你的帮助。
这真是一道设计题。在 Model
class 设计中,您要么需要决定对象所有权,要么将决定推迟到调用代码。在后一种情况下,你不能有默认参数(除非你想有全局常量 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;
}
你的问题是编译错误吗?有多种方法可以解决编译错误,但鉴于您的问题是关于从抽象 classes 继承,我将重点关注它。
首先,根据规定,您的 Animal
class 是 而不是 摘要 class .抽象 class 无法实例化,因为它的所有方法都是纯虚拟的。在 C++ 中,纯虚函数由 virtual
关键字前缀指定, 和 在其定义中以 = 0
为后缀。例如
...
virtual void print() = 0;
...
通过将您的 Animal
class 抽象为 class:
可以编译以下代码
#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
不是 抽象 class 因为它提供了 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++ 中完全可行:将默认值分配给某个函数参数列表中的基 class 指针。
重要:正如评论者正确指出的那样,您编码的模式很危险:您的界面使得用户可以 可选地 提供一个Animal
实例。问题是:如果 Model
创建者拥有,那么可以合理地论证他正确地拥有该对象。如果他不这样做,那么您的构造函数 将 创建一个新的 Animal
实例,但 Model
既不会取得该对象的所有权,也不会提供接口用户可以获得新 Animal
实例的所有权。因此,这会造成内存泄漏。同样,代码风险是 Model
构造函数中使用的 Animal
实例的所有权不明确。
我想我想出了适合我的情况的最佳解决方案。
#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;
}
我正在尝试做这样的事情:
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;
}
我们如何设置抽象 class 指针的默认值以及如何像从 main 那样将它们作为参数传递?
我也希望能够像这样仅在一行中传递来自 main 的参数,而无需之前进行初始化。
任何人都可以帮助我在 C++ 中如何做这些事情吗?
我已经尝试和搜索了很多但没有运气。
我正在寻找一种解决方法来做这样的事情,其中我们使用抽象 classes 作为其他 classes 的参数。
我知道不能将对象分配给指针,我只是不知道该怎么做才能满足我的要求,抽象 class 作为具有默认值的参数。
这是我对精确代码的最新尝试,但不幸的是 new
,有谁知道如何摆脱 new
并达到预期的结果?
注:
我的实际代码相当复杂,基本上使用抽象 class 进行多态性并将这些抽象 class 作为参数传递给另一个具有默认参数的 class ,如果有 ANY 其他方式来做类似的事情我真的很感激你的帮助。
这真是一道设计题。在 Model
class 设计中,您要么需要决定对象所有权,要么将决定推迟到调用代码。在后一种情况下,你不能有默认参数(除非你想有全局常量 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;
}
你的问题是编译错误吗?有多种方法可以解决编译错误,但鉴于您的问题是关于从抽象 classes 继承,我将重点关注它。
首先,根据规定,您的 Animal
class 是 而不是 摘要 class .抽象 class 无法实例化,因为它的所有方法都是纯虚拟的。在 C++ 中,纯虚函数由 virtual
关键字前缀指定, 和 在其定义中以 = 0
为后缀。例如
...
virtual void print() = 0;
...
通过将您的 Animal
class 抽象为 class:
#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
不是 抽象 class 因为它提供了 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++ 中完全可行:将默认值分配给某个函数参数列表中的基 class 指针。
重要:正如评论者正确指出的那样,您编码的模式很危险:您的界面使得用户可以 可选地 提供一个Animal
实例。问题是:如果 Model
创建者拥有,那么可以合理地论证他正确地拥有该对象。如果他不这样做,那么您的构造函数 将 创建一个新的 Animal
实例,但 Model
既不会取得该对象的所有权,也不会提供接口用户可以获得新 Animal
实例的所有权。因此,这会造成内存泄漏。同样,代码风险是 Model
构造函数中使用的 Animal
实例的所有权不明确。
我想我想出了适合我的情况的最佳解决方案。
#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;
}