【问题标题】:pure virtual class c++纯虚类 c++
【发布时间】:2014-04-01 21:01:25
【问题描述】:

我在尝试从抽象类创建子类时遇到问题

class people 
{
public: 
   people();
   ~people();
   virtual int comparable(people*); 
   void order(people**,int);
};

我的子类

class worker : public people
{
private: 
  int salary;
public: 
  worker();
  ~worker(); 
  int comparable (people*);
}; 

我需要按薪水(来自工人)订购一个动态的人员数组,但我无法匹配人员数组[j]=worker a;

你有什么建议? 然后我如何调用函数顺序?因为无法创建人员对象

【问题讨论】:

  • 您想按salarypeople 进行排序,但不是people 没有salary,那么您打算怎么做呢?你想让salary 成为people 课程的一部分吗?是否要改为使用 workers 的动态列表?
  • 解释什么array[j]=worker a;应该是意思或做。这甚至不是有效的语法。
  • 你的想法是对的。在worker 中实现comparable,您可以在其中使用薪水。
  • 你提到的类中没有pure virtual 声明?你的意思是virtual int comparable(people*) = 0;

标签: c++ class virtual abstract


【解决方案1】:

提供一个纯虚函数来比较两个people

#include <algorithm>
#include <utility>
#include <stdexcept>

class people 
{
   public: 
      people();
      ~people();
      virtual int compare(const people* rhs) const = 0; 
};

worker中实现compare函数。

class worker : public people
{
   private: 
      int salary;
   public: 
      worker();
      ~worker(); 
      virtual int compare(const people* rhs) const
      {
         const worker* rhsw = dynamic_cast<const worker*>(rhs);
         if ( NULL == rhsw )
         {
            throw std::invalid_argument("rhs");
         }
         return (this->salary - rhsw->salary);
      }
}; 

提供一个可以在std::sort 中使用的函子。

struct people_compare
{
   bool operator()(people* lhs, people* rhs) const
   {
      return (lhs->compare(rhs) < 0);
   }
};

使用std::sort 和上面的仿函数对人员列表进行排序。

void order(people** plist, int num)
{
   std::sort(plist, plist+num, people_compare());
}

【讨论】:

    【解决方案2】:

    这似乎是一件相当奇怪的事情,如果您希望按照他们的薪水对people 的某种集合进行排序,那么在people 中有一个salary 变量会更有意义。

    我也不清楚comparable 的返回值是什么,但这里有一个基于salary 排序的解决方案,并假设people 对象不是worker 类型(或派生的)有零工资。它返回 0 表示相同的薪水,1 表示“此对象的薪水高于传入的对象”,而 -1 表示“薪水低于传入的对象”。

    但是请注意,这是一个非常糟糕的设计,通常不应该像这样使用dyanamic_cast

    int worker::comparable(people *p)
    {
       worker *w = dynamic_cast<worker*>(p); 
       int wsalary = 0;
       if (w) 
          wsalary = w->salary;
       if (salary == wsalary) return 0;
       if (salary > wsalary) return 1;
       return -1;
    }
    

    【讨论】:

      【解决方案3】:

      如果您的数组包含人员实例,那么其中一些实例实际上可能不是工作实例(而是派生自人员的某些其他类的实例),在这种情况下,您不能按薪水对数组进行排序,因为它不是保证您的所有数组项实际上都有薪水。

      好的,此时您可能想说,在这种特殊情况下,您实际上保证所有人员指针都是工作实例。即使在这种情况下,您的设计也很糟糕,因为如果您保证所有人的指针都是工作类,那么为什么不对工作指针数组执行排序操作???

      前面的解释表明,将比较操作作为虚方法放入基类中并不是一个好主意,因为不同子类的实例之间的比较通常是未定义或无效的操作。

      看看一些高级语言。即使那些提供某种通用虚拟比较运算符的人也已切换到某种通用/模板化解决方案,其中接口具有类型参数,因此比较接口是类型安全的,无需任何类型检查和向下转换。 (type_check+downcast == C++ 中的 dynamic_cast)。

      如果您仍然想在基类中使用通用虚拟方法解决问题,那么您必须按照 Mats Petersson 的建议执行动态转换,并且您要么决定支持当前类之外的其他类 ( this) 实例,或者如果有人传入不受支持的类的实例,您可能想要抛出异常。这很糟糕,原因有很多。涉及 dynamic_cast 的 C++ 代码通常设计得不好,dynamic_cast 是一种 OOP 反模式(就像它在类型检查之后执行的向下转换......)。 dynamic_cast 的另一个问题是,使用 dynamic_cast 的糟糕设计通常会将许多其他编译时错误转换为仅在某些特殊情况/情况下发生的运行时错误(不幸的是,通常在最终用户的机器上,具体取决于代码覆盖率您的测试用例及其执行频率)。

      【讨论】:

        【解决方案4】:

        我需要按薪水(来自工人)订购一个动态的人员数组,但是 [...]。你有什么建议?然后怎么调用函数order

        我会考虑重构您的代码。对于动态数组,我会使用std::vector,对于排序,您可以使用std::sort

        如果您想要一个解耦系统,您可能应该将“容器和排序特定代码”从 personworker 类中移开。

        事实上,在这种情况下,您甚至根本不需要基类或公共继承。您可以为层次结构的每个类定义一个比较函数。特别是worker

        bool compare(const worker &a, const worker &b) {
            // return true if a is < b
            // example follows
            return a.salary < b.salary;
        }
        

        最后,你得到了:

        class worker {
            // ...
        };
        
        std::vector<worker> workers;
        

        当您需要对workers 向量进行排序时,您可以这样做:

        std::sort(workers.begin(), workers.end(), compare);
        

        如果能够做到worker_a &lt; worker_b 是有意义的(即使基于薪水的歧视并不是一种流行的观点),您可以实施operator&lt;

        struct worker {
            bool operator<(const worker& rhs) {
                // for example
                return salary < rhs.salary
            }
        };
        

        只需排序:

        std::sort(workers.begin(), workers.end());
        

        【讨论】:

          猜你喜欢
          • 2010-11-13
          • 1970-01-01
          • 1970-01-01
          • 2011-09-08
          • 1970-01-01
          • 1970-01-01
          • 2018-05-02
          • 2012-10-01
          • 2013-06-09
          相关资源
          最近更新 更多