C++ 多态性:如何创建派生 class 对象
C++ polymorphism: how to create derived class objects
我有一个名为 BaseStrategy
的抽象基 class。它包含一个纯虚函数calculateEfficiency()
。有两个 classes ConvolutionStrategy
和 MaxPoolStrategy
派生自这个基础 class 并实现它们自己的特定版本 calculateEfficiency()
.
这是一些代码:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
现在我有另一个 class 叫做 StrategyAssigner
。它有方法 calculateAllLayerEfficiencies()
,其目的是遍历网络中的所有层。根据层的类型,有一个 switch 语句,应该根据层类型调用正确的 calculateEfficiency()
。
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
我的问题是,我是否应该将对象 Convolution 和 MaxPool 的引用存储在 class StrategyAssigner
中,以便我可以调用相应的 calculateEfficiency()
.
或者您能否建议一种更好的调用方式 calculateEfficiency()
。我真的不知道如何创建对象(听起来很愚蠢)。
我不能让 calculateEfficiency()
静态,因为我需要它们是虚拟的,这样每个派生的 class 都可以实现自己的公式。
如果您包含完整的代码,我可以给出更详细的答案,但您需要存储使用派生 class 实例初始化的 BaseStrategy 指针。这是根据您的一些代码制作的示例:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
请注意,这不会编译,因为我没有从您发布的代码中获得足够的细节来编译它,但这展示了如何以您需要的方式利用多态性。
另外,我使用了智能指针来进行内存管理;请自行决定使用这些。
你确实可以在这里使用运行时多态性:
- 声明
~BaseStrategy
虚拟(您已经在做 ;-)
- 如果您永远不会实例化一个
BaseStrategy
,请将其中一个方法声明为虚拟纯方法,例如calculateEfficiency
(你也已经在做了!)。我会制作该方法 const
,因为它看起来不会修改实例。它需要是 public,因为它需要从 StrategyAnalyser
. 访问
- 在每个子 class 中将
calculateEfficiency
声明为 virtual
和 override
。如果您不想子 class 覆盖它,它也可以是 final
。
- 我会在
StrategyAssigner
处保留 std::vector
个指向 BaseStrategy
的智能指针。如果您认为 class 不会共享这些指针,则可以使用 unique_ptr
s。
- 现在的关键点是创建子classes 的堆实例并将它们分配给基class.
的指针
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
- 然后,当您使用这些指向
BaseStrategy
的指针中的任何一个调用 calculateEfficiency
时,运行时多态性将启动,它将是 subclass 的方法将实际调用。
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30
我有一个名为 BaseStrategy
的抽象基 class。它包含一个纯虚函数calculateEfficiency()
。有两个 classes ConvolutionStrategy
和 MaxPoolStrategy
派生自这个基础 class 并实现它们自己的特定版本 calculateEfficiency()
.
这是一些代码:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
现在我有另一个 class 叫做 StrategyAssigner
。它有方法 calculateAllLayerEfficiencies()
,其目的是遍历网络中的所有层。根据层的类型,有一个 switch 语句,应该根据层类型调用正确的 calculateEfficiency()
。
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
我的问题是,我是否应该将对象 Convolution 和 MaxPool 的引用存储在 class StrategyAssigner
中,以便我可以调用相应的 calculateEfficiency()
.
或者您能否建议一种更好的调用方式 calculateEfficiency()
。我真的不知道如何创建对象(听起来很愚蠢)。
我不能让 calculateEfficiency()
静态,因为我需要它们是虚拟的,这样每个派生的 class 都可以实现自己的公式。
如果您包含完整的代码,我可以给出更详细的答案,但您需要存储使用派生 class 实例初始化的 BaseStrategy 指针。这是根据您的一些代码制作的示例:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
请注意,这不会编译,因为我没有从您发布的代码中获得足够的细节来编译它,但这展示了如何以您需要的方式利用多态性。
另外,我使用了智能指针来进行内存管理;请自行决定使用这些。
你确实可以在这里使用运行时多态性:
- 声明
~BaseStrategy
虚拟(您已经在做 ;-) - 如果您永远不会实例化一个
BaseStrategy
,请将其中一个方法声明为虚拟纯方法,例如calculateEfficiency
(你也已经在做了!)。我会制作该方法const
,因为它看起来不会修改实例。它需要是 public,因为它需要从StrategyAnalyser
. 访问
- 在每个子 class 中将
calculateEfficiency
声明为virtual
和override
。如果您不想子 class 覆盖它,它也可以是final
。 - 我会在
StrategyAssigner
处保留std::vector
个指向BaseStrategy
的智能指针。如果您认为 class 不会共享这些指针,则可以使用unique_ptr
s。 - 现在的关键点是创建子classes 的堆实例并将它们分配给基class. 的指针
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
- 然后,当您使用这些指向
BaseStrategy
的指针中的任何一个调用calculateEfficiency
时,运行时多态性将启动,它将是 subclass 的方法将实际调用。
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30