c++ - 抽象类和虚拟构造函数的替代方法

标签 c++ c++11 design-patterns abstract-class

假设我有以下代码:

class Block{
private:
  data Data;
public:
  data getData();
  Block(arg3 Arg3, arg4 Arg4);
};

其实,构建区 block 的方式有很多种,但总是使用相同的成员Data和方法getData(),唯一的区别是如何构建区 block 。换句话说,唯一的区别是构造函数......

我可以分解部分代码,在抽象类中定义和声明 getData,而不是为每个构建过程编写不同的类,如果在 c++ 中有虚拟构造函数之类的东西,我可以为每个派生的代码编写不同的代码类对应不同的构建过程。

我对这类事情没有太多经验,所以我想知道是否有虚拟构造函数的替代方案?或者可能是进行这种因式分解的不同方法?

PS:我知道https://isocpp.org/wiki/faq/virtual-functions#virtual-ctors但是关于我想做的事情似乎很复杂,这似乎很常见......我只想分解几个类之间的共享代码,这对应于除构造函数之外的所有内容。而且我想强制对应于其他构建过程的新类实现一个新的构造函数。

关于我的具体情况的更多细节:

我有一个使用 block 的算法,它不依赖于它们的构建过程,所以我使用模板参数实现了该算法,以表示一个与其构建过程无关的 block 。但是我使用了一些方法及其构造函数,所以我需要代表 block 的类都具有我需要的相同类型的方法和相同的构造函数以将它们用作我的算法实现的模板参数。这就是为什么我想到抽象类,强制一个新实现的类代表 block 具有我实现的算法中需要的方法和构造函数。可能这是一个糟糕的设计模式,这就是我被困的原因......

编辑

感谢您到目前为止的回答。我试着说得有点笼统,但我觉得它实际上太模糊了,即使我最后给出了细节。所以这就是我想做的:我有一个 Matrix 类,如下所示

// Matrix.hpp
template<typename GenericBlock> class Matrix{
  std::vector<GenericBlock> blocks;
  Matrix(arg1 Arg1, arg2 Arg2);
};

template<typename GenericBlock>
Matrix<GenericBlock>::Matrix(arg1 Arg1, arg2 Arg2){
  // Do stuff
  GenericBlock B(arg3 Arg3, arg4 Arg4);
  B.getData();
}

block 实际上是压缩的,有几种压缩它们的方法,它不会改变 Matrix 类中的任何内容。为了避免为每种压缩技术编写一个矩阵类,我使用了一个模板参数,如您所见。所以我只需要为每种压缩技术编写一个类,但它们必须具有相同的方法和构造函数参数才能与 Matrix 兼容。

这就是为什么我想到做一个抽象类,为每个压缩技术编写一个类。在抽象类中,我会在 Matrix 中编写所有需要的内容,以便每个派生类都与 Matrix 兼容。我的示例中现在的问题是:我可以在抽象类中定义 getData,因为它总是相同的(例如,Data 可以是行数)。派生类唯一真正需要定义的是构造函数。

一个解决方案是不使用抽象类,而是使用 protected 构造函数。但它并不强制新派生类重新实现构造函数。这就是为什么我被困住了。但我认为这个问题很普遍,足以引起其他人的兴趣。那么在这种情况下是否有替代虚拟构造函数的方法? (可能是工厂模式,但对于这样一个常见问题来说似乎很复杂)如果没有,是否有更好的方法来实现一个矩阵类,其 block 可以以不同的方式构建,即其构造函数可以彼此不同,而有相同的数据和一些共同的方法?

PS:我对产生低秩矩阵的压缩技术很感兴趣,这就是为什么数据总是相同的,但构建过程却不同。

最佳答案

从您目前分享的内容来看,您不清楚为什么需要抽象类或虚拟构造函数。用于构建 block 的每种方式的工厂函数将执行以下操作:

class Block {
  Data data;
public:
  Block(Data d) : data(std::move(d)) {}
  Data getData();
};

Block createABlock() { return Block{Data{1.0, 2.0, 3.0}}; }  
Block createBBlock() { return Block{Data{42.0, 3.14, 11.6}}; }

int main() {
  auto b1 = createABlock();
  auto b2 = createBBlock();
}

Live demo .

也许这需要用一个抽象工厂来扩展,这样你就可以传递一个通用的 block 工厂:

using BlockFactory = std::function<Block()>;

int main() {   
  BlockFactory f = createABlock;
  auto b3 = f();   
}

编辑: 关于您的编辑,您的建议works fine .您不需要虚拟构造函数。模板类型 GenericBlock 只需满足模板定义的隐式接口(interface)即可。它不需要派生自特定的基类(尽管它可以)。唯一需要的是它必须有一个构造函数,该构造函数采用一组特定的参数和一个 getData 方法。您拥有的是编译时静态多态性,虚函数用于运行时动态多态性。

继承会很好地工作,但正如我上面所说,我很想使用某种工厂。您可能不需要模板化整个 Matrix 类,因为只有构造函数需要工厂。如果工厂在编译时已知,则可以将其作为模板参数传递:

class Matrix {
  std::vector<Block> blocks;
 public:

  template<typename BlockFactory>
  Matrix(BlockFactory f);
};

template<typename BlockFactory>
Matrix::Matrix(BlockFactory f){

  // Do stuff...

  Block B = f();
  auto data = B.getData();
  for (auto v : data)
    std::cout << v << " ";
  std::cout << "\n";
}

int main() {
  Matrix ma(createABlock);
  Matrix mb(createBBlock);
}

Live demo .

关于c++ - 抽象类和虚拟构造函数的替代方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44249971/

相关文章:

c++ - 如何从一组派生类创建一个列表?

c++ - 从 C++ 中的另一个类更改数组值

c++ - 是否可以在不向函数传递参数的情况下获取函数的返回类型?

java - 覆盖现有的对象图?

c++ - boost程序选项的parse_config_file如何解析multitoken

c++ - 可以在 C++ 中使用 dynamic_cast 进行向上转换和向下转换

c++ - 模板基类的子类的模板特化

c++ - 如何构造具有唯一指针的 vector

c# - 将数据库上下文提供给对象工厂

c# - 工厂模式很多参数需要提示