我有一个名为Animal
的抽象类和一个名为cow
的派生类。
Cow
在Animal
中提供了纯虚函数的定义。
我想创建一个名为AnimalWrapper
的类,该类继承自Animal
。我希望方法AnimalWrapper.speak()
仅调用cow.speak()
。
我是否只需要在animalwrapper类中引用cow
对象,以便我可以调用非静态方法说话?
我该怎么做?
#include<iostream>
#include<cstdlib>
using namespace std;
#include <string>
class Animal // This Animal is an abstract base class
{
public:
Animal(){};
virtual const char* speak() = 0; //pure virtual function
};
class Cow: public Animal
{
public:
Cow(){};
virtual const char* speak() {
cout << "I am a cow" << endl;
return "Moo ";
}
};
class AnimalWrapper: public Animal
{
public:
AnimalWrapper(){}
virtual const char* speak() {
cout << "Calling cow class speak() method" << endl;
//Call Cow::speak()
return "Moo";
}
};
int main()
{
AnimalWrapper AnimalWrapper_obj ;
std::cout << AnimalWrapper_obj.speak() << '\n';
}
答案 0 :(得分:1)
假设您要扩展使用中的API,但不能对其本身进行修改,那么我得出结论,您想提供一个并行层次结构:
namespace wrapped
{
class Animal
{
public:
virtual ~Animal();
virtual std::string speak();
};
class Cow : public Animal
{
public:
std::string speak() override;
unsigned int giveMilk() { return 77; }
};
}
namespace wrapping
{
class Animal
{
protected:
wrapped::Animal& animal;
Animal(wrapped::Animal& animal)
: animal(animal)
{ }
public:
virtual ~Animal() { }
// does not need to be virtual, we can profit from
// polymorphism of referred object...
//
// still it CAN be virtual, if you want to allow derived
// wrappers as well to modify the inherited speak!
std::string speak()
{
return animal.speak();
}
};
class Cow : public Animal
{
public:
Cow(wrapped::Cow& cow)
: Animal(cow)
{ }
// speak is inherited
unsigned int giveMilk()
{
// don't need dynamic cast as we passed a reference
// to cow object to base class constructor...
return static_cast<wrapped::Cow&>(animal).giveMilk();
}
};
}
如果Cow
从Animal
继承 可以使用的变体可以使您编写的代码更少:
namespace wrapping
{
class Animal : private virtual wrapped::Animal
{
public:
using wrapped::Animal::speak;
};
class Cow : public Animal, private wrapped::Cow
{
public:
using wrapped::Cow::speak;
};
}
但是,如果Cow
不是虚拟继承的,则您的包装Cow
将继承wrapped::Animal
的两个实例,这将导致许多问题,此处暂不讨论。
但是,如果您在speak
中覆盖wrapping::animal
,则需要在wrapping::Cow
中提供 finaloverrer 来解决两个继承的覆盖的变体之间的歧义speak
。
实际上,您可以可以公开地从已包装的基类继承,那么您将不再需要using声明(尽管仍然存在最终的替代者问题),但这将允许包装类和包装类,您很可能想避免。
答案 1 :(得分:0)
根据您的评论,这里是一个AnimalWrapper类的示例,该类使用move语义获取Cow实例的外部引用。由于它是移动构造函数,而不是复制构造函数,因此在使用原始对象时应格外小心。
如果要保留Cow的原始实例,则可能需要复制构造函数(但您将复制Cow实例)。
您还可以将指针或引用存储在类Cow * cowInstance
或Cow& cowInstance
中),但是您可能会以悬空的指针/引用结尾(因此在这里使用了移动语义)。 >
#include<iostream>
#include<cstdlib>
#include <memory>
// using namespace std; // <= Using namespace std is considered bad practice
#include <string>
class Animal // This Animal is an abstract base class
{
public:
Animal(){}
virtual ~Animal() {} // Do some research about the difference between virtual and non virtual destructor in C++
virtual std::string speak() = 0; //pure virtual function
};
class Cow: public Animal
{
public:
Cow(){}
Cow(const Cow& cow) = delete;
Cow(Cow&& _cow) {std::cout << "Move constructor " << std::endl;}
virtual ~Cow() {}
// virtual const char* speak() { // <= Use std::string in c++
virtual std::string speak() {
++m;
std::cout << "I am a cow : "<< m << std::endl;
return std::string("Mooo");
}
private:
int m = 0;
};
class AnimalWrapper // : public Animal // <= This is unnecessary
{
public:
AnimalWrapper(std::unique_ptr<Cow> _cow) : cowInstance((std::move(_cow))) {
}
std::string speak() {
std::cout << "Calling cow class speak() method" << std::endl;
return cowInstance->speak();
}
private:
std::unique_ptr<Cow> cowInstance;
};
int main()
{
std::unique_ptr<Cow> cow(new Cow);
cow->speak();
std::cout << "Hello, world!" << std::endl;
AnimalWrapper AnimalWrapper_obj(std::move(cow));
std::cout << AnimalWrapper_obj.speak() << '\n';
}
由于您要解决的问题对我来说仍然不清楚,因此这可能不是理想/完美的解决方案。但是,这只是您根据我的理解所提出的要求的一个示例。