纯虚拟类c ++

时间:2014-04-01 21:01:25

标签: c++ class virtual abstract

我在尝试从抽象类

创建子类时遇到了问题
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] =工人a;

你建议什么? 然后我如何调用de function order?因为a无法创建人物对象

4 个答案:

答案 0 :(得分:1)

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

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

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

compare中实施worker功能。

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());
}

答案 1 :(得分:0)

看起来似乎是一件相当奇怪的事情,如果你希望对某些salary的集合进行排序,那么在people中设置一个people变量会更有意义。他们的薪水。

我还不清楚comparable的返回值是什么,但这里是基于salary进行排序的解决方案,并假设people不属于worker类型(或由此派生)的对象没有工资。它返回0表示相等的工资,1表示&#34;该对象的工资高于传入的对象&#34;和#34;工资少于在对象中传递的工资&#34;。

但请注意,这是一个非常糟糕的设计,您通常不应该像这样使用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;
}

答案 2 :(得分:0)

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

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

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

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

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

答案 3 :(得分:0)

  

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

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

如果你想要一个解耦系统,你应该移动&#34;容器并对特定代码进行排序&#34;远离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 < worker_b是有意义的(即使基于工资的歧视不是一个流行的观点),你可以实现operator<

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

只需按:

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