关于C++设计模式的问题,纯虚方法调用

Posted

技术标签:

【中文标题】关于C++设计模式的问题,纯虚方法调用【英文标题】:Question on C++ design pattern, pure virtual method called 【发布时间】:2021-04-09 02:50:44 【问题描述】:

我在尝试来自https://en.wikipedia.org/wiki/Bridge_pattern 的代码时遇到了虚拟方法问题。

错误信息是:

调用纯虚方法 在没有活动异常的情况下调用终止 中止(核心转储)

代码是用g++ -o bridge bridge.cpp -std=c++11编译的

为什么drawing_api_.DrawCircle()调用DrawingAPI中的虚函数?

#include <iostream>
#include <string>
#include <vector>


class DrawingAPI 
  public:
    virtual ~DrawingAPI() = default;
    virtual std::string DrawCircle(float x, float y, float radius) const = 0;
;

class DrawingAPI01 : public DrawingAPI 
  public:
    std::string DrawCircle(float x, float y, float radius) const override 
      return "API01.circle at " + std::to_string(x) + ":" + std::to_string(y) +
        " - radius: " + std::to_string(radius); 
    
;

class DrawingAPI02 : public DrawingAPI 
  public:
    std::string DrawCircle(float x, float y, float radius) const override 
      return "API02.circle at " + std::to_string(x) + ":" + std::to_string(y) +
        " - radius: " + std::to_string(radius); 
    
;

class Shape 
  public:
    Shape(const DrawingAPI& drawing_api) : drawing_api_(drawing_api) 
    virtual ~Shape() = default;

    virtual std::string Draw() const = 0;
    virtual float ResizeByPercentage(const float percent) = 0;

  protected:
    const DrawingAPI& drawing_api_;
;

class CircleShape: public Shape 
  public:    
    CircleShape(float x, float y, float radius, const DrawingAPI& drawing_api)
      : Shape(drawing_api), x_(x), y_(y), radius_(radius) 

    std::string Draw() const override 
        return drawing_api_.DrawCircle(x_, y_, radius_);
    

    float ResizeByPercentage(const float percent) override 
      return radius_ *= (1.0f + percent/100.0f);
    
  
  private:
    float x_, y_, radius_;
;

int main(int argc, char** argv) 
  std::vector<CircleShape> shapes 
    CircleShape1.0f, 2.0f, 3.0f, DrawingAPI01,
    CircleShape5.0f, 7.0f, 11.0f, DrawingAPI02
  ; 

  for (auto& shape: shapes) 
    shape.ResizeByPercentage(2.5);
    std::cout << shape.Draw() << std::endl;
  

  return 0;

【问题讨论】:

避免引用持有DrawingAPI。一些 Wikipedia 实现的 C++ 设计模式示例存在错误。 非常感谢,修改指针的引用后问题解决了。 【参考方案1】:

发布的代码有问题——尤其是Shape 类包含对a-DrawingAPI-object 的引用:

class Shape 
[...]

protected:
   const DrawingAPI& drawing_api_;
;

...但是它所引用的对象是一个临时对象,一旦main() 中的CircleShape 构造函数返回,就会被销毁。

避免错误的一种方法是声明 DrawingAPI01DrawingAPI02 对象,使其生命周期比引用它们的 CircleShape 对象的生命周期更长,例如通过将main() 更改为如下所示:

int main(int argc, char** argv) 
   DrawingAPI01 api01;   // declaring these up here keeps them valid
   DrawingAPI01 api02;   // until the end of main()

   std::vector<CircleShape> shapes 
      CircleShape1.0f, 2.0f, 3.0f, api01,
      CircleShape5.0f, 7.0f, 11.0f, api02
   ;

   for (auto& shape: shapes) 
      shape.ResizeByPercentage(2.5);
      std::cout << shape.Draw() << std::endl;
   

   return 0;

【讨论】:

以上是关于关于C++设计模式的问题,纯虚方法调用的主要内容,如果未能解决你的问题,请参考以下文章

C++ 纯虚函数

c++ 虚函数和纯虚函数

在运行时定义的 C++ 纯虚方法

关于c++设计模式的总结

C++纯虚函数

C++编程练习:多态实验——利用抽象类和纯虚函数,编程计算正方体球体和圆柱体的表面积和体积。