Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有返回类型为派生类的函数的派生类的抽象基类_C++_Abstract Class_Derived Class - Fatal编程技术网

C++ 具有返回类型为派生类的函数的派生类的抽象基类

C++ 具有返回类型为派生类的函数的派生类的抽象基类,c++,abstract-class,derived-class,C++,Abstract Class,Derived Class,我想强制从基类派生的所有类使用特定的API。通常,您可以使用具有纯虚拟函数的抽象基类来实现这一点。但是,如何处理返回派生类型的函数?我如何强制执行这种类型的函数 struct base { virtual base func() = 0; }; struct deriv1 : base { deriv1 func(); }; struct deriv2 : base { deriv2 func(); }; 此示例将给出一个错误,如“成员函数的抽象返回类型无效”。我已

我想强制从基类派生的所有类使用特定的API。通常,您可以使用具有纯虚拟函数的抽象基类来实现这一点。但是,如何处理返回派生类型的函数?我如何强制执行这种类型的函数

struct base
{
    virtual base func() = 0;
};

struct deriv1 : base
{
    deriv1 func();
};

struct deriv2 : base
{
    deriv2 func();
};

此示例将给出一个错误,如“成员函数的抽象返回类型无效”。我已经看到了一些建议返回指针的答案,但我并不特别想为此而使用动态内存,而跟踪所有分配的指针将是一种特殊的地狱。有什么想法吗?

当虚拟函数返回指向类的指针或引用时,允许从基类继承并重写该函数的类将返回类型更改为指向从原始返回类型派生的类的指针或引用

不能按值返回base,因为它是抽象的,所以实际上不能自己创建一个


使用虚拟函数和基类时,通常必须使用动态分配来创建对象。我建议您研究智能指针以帮助管理内存。

在您的示例中,
func
将不是“相同的函数”,因此
deriv1
deriv2
变体将不会有不同的虚拟函数

不幸的是,除了返回指针之外,别无选择—它不必是指向动态分配内存的指针(例如,您可以返回指向
this
静态对象的指针;
—但它必须是指向
base
的指针[或引用,但同样的问题也适用]

这样做的主要原因(除了“函数不能仅在返回类型上进行区分”这一事实外)是,如果您有一些类似以下内容的通用代码:

vector<base*> v;
... stuff a bunch of `dervi1` or `deriv2` objects into v. 
for(i : v)
{
    base b = i->func();
}
#include <memory> //for unique_ptr
#include <iostream>

struct Base
{
  virtual void doX() = 0;
  virtual void doY() = 0;
  virtual ~Base(){}
};

struct D1 : Base
{
  virtual void doX()
  {
    std::cout << "D1::doX()" << std::endl;  
  }
  virtual void doY()
  {
    std::cout << "D1::doY()" << std::endl;  
  }
};

struct D2 : D1
{
  virtual void doX()
  {
    std::cout << "D2::doX()" << std::endl;  
  }
  virtual void doY()
  {
    std::cout << "D2::doY()" << std::endl;  
  }
};

//From this point on you can do various things:

void driver()
{
  Base* base = new D1;//
  base->doX(); //Calls D1::doX()
  D1* d1 = new D2;
  d1->doX(); //Calls D2::doX()
}
// or...
void driver( Base* base )
{
  //A way to replace Base with D1 with D2 depending
  // on how driver was called.
}

//Finally, maybe you want a factory to create the correct
// derived type based on which factory was instantiated.

// Creates family of products, each item representing the base
// in it's hierarchy - only one shown here...
struct AbstractFactory
{
  virtual std::unique_ptr<Base> create() const = 0;
  protected:
    virtual ~AbstractFactory(){}
};

struct D1Factory : AbstractFactory
{
  //Doesn't matter if <Derived> is returned, because it adheres
  // to interface of Base (isA base), and correct functions are
  // found polymorphically 
  virtual std::unique_ptr<Base> create() const
  {
    return std::unique_ptr<Base>( new D1 ); 
  }
};
struct D2Factory : AbstractFactory
{
  //Doesn't matter if <Derived> is returned, because it adheres
  // to interface of Base (isA base), and correct functions are
  // found polymorphically 
  virtual std::unique_ptr<Base> create() const
  {
    return std::unique_ptr<Base>( new D2 ); 
  }
};

void driver( const AbstractFactory& factory )
{
  std::unique_ptr<Base> base( factory.create() );
  base->doX();
  base->doY();
  //Memory deallocated automagically...
}

int main()
{
  driver( D1Factory() );
  driver( D2Factory() );
}
向量v; …将一堆'dervi1'或'deriv2'对象填充到v中。 (i:v) { 基本b=i->func(); } 现在,要么您现在将
deriv1
deriv2
切割成
base
大小,要么您将大于
base
的对象复制到
base
大小的对象中,这两种方法都没有任何好处。[我假设在这个实际用例中,
deriv1
deriv2
实际上与
base
在很多方面不同于对象的名称-否则,这是毫无意义的。
deriv1
deriv2
当然是从
base
继承的]

换句话说,您不能用
=
复制未知类型的对象。如果您必须知道它返回的类型,那么使用虚拟函数是绝对没有意义的

基本上是说“如果您想在代码中用deriv2替换deriv1,您需要实现这些函数”

从您上面的报价来看,您似乎想要这样的产品:

vector<base*> v;
... stuff a bunch of `dervi1` or `deriv2` objects into v. 
for(i : v)
{
    base b = i->func();
}
#include <memory> //for unique_ptr
#include <iostream>

struct Base
{
  virtual void doX() = 0;
  virtual void doY() = 0;
  virtual ~Base(){}
};

struct D1 : Base
{
  virtual void doX()
  {
    std::cout << "D1::doX()" << std::endl;  
  }
  virtual void doY()
  {
    std::cout << "D1::doY()" << std::endl;  
  }
};

struct D2 : D1
{
  virtual void doX()
  {
    std::cout << "D2::doX()" << std::endl;  
  }
  virtual void doY()
  {
    std::cout << "D2::doY()" << std::endl;  
  }
};

//From this point on you can do various things:

void driver()
{
  Base* base = new D1;//
  base->doX(); //Calls D1::doX()
  D1* d1 = new D2;
  d1->doX(); //Calls D2::doX()
}
// or...
void driver( Base* base )
{
  //A way to replace Base with D1 with D2 depending
  // on how driver was called.
}

//Finally, maybe you want a factory to create the correct
// derived type based on which factory was instantiated.

// Creates family of products, each item representing the base
// in it's hierarchy - only one shown here...
struct AbstractFactory
{
  virtual std::unique_ptr<Base> create() const = 0;
  protected:
    virtual ~AbstractFactory(){}
};

struct D1Factory : AbstractFactory
{
  //Doesn't matter if <Derived> is returned, because it adheres
  // to interface of Base (isA base), and correct functions are
  // found polymorphically 
  virtual std::unique_ptr<Base> create() const
  {
    return std::unique_ptr<Base>( new D1 ); 
  }
};
struct D2Factory : AbstractFactory
{
  //Doesn't matter if <Derived> is returned, because it adheres
  // to interface of Base (isA base), and correct functions are
  // found polymorphically 
  virtual std::unique_ptr<Base> create() const
  {
    return std::unique_ptr<Base>( new D2 ); 
  }
};

void driver( const AbstractFactory& factory )
{
  std::unique_ptr<Base> base( factory.create() );
  base->doX();
  base->doY();
  //Memory deallocated automagically...
}

int main()
{
  driver( D1Factory() );
  driver( D2Factory() );
}
#包含//以获得唯一的ptr
#包括
结构基
{
虚空doX()=0;
虚空doY()=0;
虚拟~Base(){}
};
结构D1:基础
{
虚拟void doX()
{

std::cout我不确定你想做什么。为什么你要按值返回类型?你能给函数提供真实的名称吗?通常在克隆时,一个函数会返回一个指向派生类型的引用或指针。如果内存管理是一个问题,请返回一个智能指针(例如google shared_ptr).基本上,我不想使用base,甚至不想做任何多态性。我只想创建一个API,以确保从base派生的任何类都能在相同的情况下工作。基本上,这是一种说法,“如果您想在代码中用deriv2替换deriv1,您需要实现这些函数”这是唯一的使用案例。这个特定的使用案例不值得使用智能指针和动态内存带来麻烦或性能损失。什么性能损失?使用探查器测量性能,而不是假设。是的,但我提出的问题不是如何处理正常的函数调用,而是返回Se类型等于派生类。参见我的例子中的返回类型。我的意思是:为什么需要这个?给出一个实名的具体例子。我认为你的困惑来自GC语言,实际上这些语言返回了后来垃圾收集的引用。C++中的堆栈可以实现这些。(使用智能指针包装资源).据我所知,没有任何语言具有切片功能-即,当派生类型被切片时,它将失去其虚拟部分,并成为基础。这对于引用和指针是可以接受的,因为它们不能被切片。@Wernerrasmus是一个通用的3d向量旋转类,从中派生出两个类,AngleAxisRotator和QuaternionRotator。q中的函数然后,uestion将是一个组成两个旋转的函数