Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 比较C+中的派生类+;无动态投射或静态下投射_C++_Oop - Fatal编程技术网

C++ 比较C+中的派生类+;无动态投射或静态下投射

C++ 比较C+中的派生类+;无动态投射或静态下投射,c++,oop,C++,Oop,我试图比较一个公共基类的对象。在任何情况下,当两个对象的类不同或对象特定的值不同时,比较都应该失败(例如,输出失败字符串)。理想情况下,比较是以某种方式强制执行的,这样一个新的派生类也必须为其类的成员编写一个比较函数。下面是一个代码示例: #include <iostream> #include <string> #include <vector> class Vehicle { public: virtual std::string compare

我试图比较一个公共基类的对象。在任何情况下,当两个对象的类不同或对象特定的值不同时,比较都应该失败(例如,输出失败字符串)。理想情况下,比较是以某种方式强制执行的,这样一个新的派生类也必须为其类的成员编写一个比较函数。下面是一个代码示例:

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

class Vehicle 
{ 
public:
  virtual std::string compareTo(Vehicle* v) = 0;
};

class Bicycle : public Vehicle
{
public:
  Bicycle() { color_ = "red"; }
  std::string compareTo(Vehicle* v) { return "We're different vehicles."; }
  std::string compareTo(Bicycle* b) { return color_.compare(b->color_) ? "We're different bicycles." : "We're the same bicycle."; }

private:
  std::string color_;
};

class Car : public Vehicle
{
public:
  Car() { style_ = "sedan"; }
  std::string compareTo(Vehicle* v) { return "We're different vehicles."; }
  std::string compareTo(Car* c) { return style_.compare(c->style_) ? "We're different cars." : "We're the same car."; }

private:
  std::string style_;
};

int main()
{
  Vehicle* compareFrom = new Bicycle();

  std::vector<Vehicle*> compareTos;
  compareTos.push_back(new Bicycle());
  compareTos.push_back(new Car());

  std::vector<Vehicle*>::iterator it;
  for (it = compareTos.begin(); it != compareTos.end(); ++it)
    std::cout << compareFrom->compareTo(*it) << std::endl;

  return 0;
}
#包括
#包括
#包括
等级车辆
{ 
公众:
虚拟标准::字符串比较器(车辆*v)=0;
};
自行车类别:公共车辆
{
公众:
自行车(){color=“red”;}
string compareTo(Vehicle*v){返回“我们是不同的交通工具。”;}
std::string compareTo(Bicycle*b){return color_u.compare(b->color_u)?“我们是不同的自行车。”:“我们是同一辆自行车。”;}
私人:
std::字符串颜色;
};
车辆类别:公共车辆
{
公众:
Car(){style=“sedan”;}
string compareTo(Vehicle*v){返回“我们是不同的交通工具。”;}
std::string compareTo(Car*c){return style_u.compare(c->style_u)?“我们是不同的车。”:“我们是同一辆车。”;}
私人:
std::字符串样式;
};
int main()
{
车辆*compareFrom=新自行车();
std::向量比较;
比较。向后推(新自行车());
比较。推回(新车());
std::vector::it迭代器;
for(it=compareTos.begin();it!=compareTos.end();+it)
std::cout compareTo(*it)您想要(即,选择基于多个变量动态调用哪个函数,而不仅仅是“this”)。这是因为您需要以某种方式检查类型,否则编译器将对类型进行静态分析,并选择要调用的函数(车辆中的虚拟函数)

没有办法。
dynamic\u cast
是您的朋友,但出于性能(或其他)原因,您可能希望推出自己的RTTI系统。(维基百科文章给出了一种方法。)

std::string Bicycle::compareTo(Vehicle*v){
if(自行车*b=动态(v)){
返回比较到(b);
}否则{
return“我们是不同的车辆。”;
}
}
中有一个此模式的实现,如果您有许多需要比较的类型,它可能会有所帮助


<> P>多语言调度不支持C++语言,也不支持大多数主流语言。有一个建议将它添加到C++ 11,但是看到这个,我认为它被拒绝了(因为已知和未知)。动态链接的问题,C++标准不知道。

如果你的编译器中启用了RTTI,你可以使用Type ID()操作符,但是这将要求你的类是多态的。

你的代码有一个大问题,就是它不容易扩展(违反)。。但是,您可以将比较委托给基类方法

此外,如果您想要强制语义(一件好事),那么您将无法避免向下转换,抱歉

为了使其健壮和可扩展

  • 使基本方法纯虚拟
  • 为比较对象类型的基本方法提供一个实现(是的,这很有效!即使它是纯虚拟的)
  • 在派生类中,使用基类的实现来测试类型是否相等,然后执行实际的逻辑检查
  • #包括
    #包括
    #包括
    #包括
    结构车辆{
    虚拟布尔比较(车辆常数和其他)常数=0;
    };
    bool车辆::与(车辆常数和其他)常数进行比较{
    返回typeid(*this)=typeid(其他);
    }
    结构车:车辆{
    字符串颜色;
    car(标准::字符串常量和颜色):颜色(颜色){}
    bool比较(车辆常数和其他)常数{
    bool结果=车辆::与(其他)进行比较;
    返回结果和(颜色==静态_cast(其他).color);
    }
    };
    结构自行车:汽车{
    内辐条;
    自行车(内部辐条):辐条(辐条){}
    bool比较(车辆常数和其他)常数{
    bool结果=车辆::与(其他)进行比较;
    返回结果和(辐条==静态_投射(其他).spokes);
    }
    };
    int main(){
    c1车(“蓝色”);
    c2车(“红色”);
    单车b1(42);
    
    std::cout我通常使用基类中的“kind”成员来实现这一点。我发现这有几个优点:

    • 性能-无需虚拟函数调用和动态强制转换
    • 通过对每个类类型使用不同的“位”,可以进行更高级别的比较。例如,“独轮车”和“自行车”可能都是人力驱动的,因此您可以轻松地将其与主要类型分开检查
    种类类型如下所示:

        enum Kind {
          HUMAN_POWERED  = (0x1 << 0),
          MOTOR_POWERED  = (0x1 << 1),
          BICYCLE        = (0x1 << 2) | HUMAN_POWERED,
          UNICYCLE       = (0x1 << 3) | HUMAN_POWERED,
          CAR            = (0x1 << 4) | MOTOR_POWERED
        };
    

    我的坏,注意String。CaseRead()在字符串匹配时返回0。为什么你认为自己“陷入”动态的铸造?@ MaKe从我读过的,动态铸造不应该在一个“适当的”。面向对象的设计。因为我从底层开始做这个设计,我想做的对。我在C++中不是那么棒,因此评论,但是你能不能只在一个覆盖下,如果你改变了类型,它会编译,但是只有一个签名会被调用?如果不是,你为什么不跟车去做?dynamic@aardvarkk:是的,如果你能用虚拟函数来解决调用,那就更好了。但是虚拟函数只依赖于一个参数,所以你需要手动检查其他东西,看看我的扩展答案。我看到的多重分派的问题是,你似乎必须为每一个其他类型实现一个函数来进行比较。为了便于检查举例来说,如果我有100种类型的车辆,每个车辆子类都必须能够与其他车辆进行比较。而且,如果你忘记实现任何类型的车辆,你似乎会遇到一个潜在的无限循环。这种动态方法很好地避免了这一点,我只是认为也许我遗漏了一些超级聪明的东西。@Aardvark:嗯,超级聪明的没有C++支持的东西,所以你必须
    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <typeinfo>
    
    struct vehicle {
        virtual bool compare_to(vehicle const& other) const = 0;
    };
    
    bool vehicle::compare_to(vehicle const& other) const {
        return typeid(*this) == typeid(other);
    }
    
    struct car : vehicle {
        std::string color;
    
        car(std::string const& color) : color(color) { }
    
        bool compare_to(vehicle const& other) const {
            bool result = vehicle::compare_to(other);
            return result and (color == static_cast<car const&>(other).color);
        }
    };
    
    struct bike : vehicle {
        int spokes;
    
        bike(int spokes) : spokes(spokes) { }
    
        bool compare_to(vehicle const& other) const {
            bool result = vehicle::compare_to(other);
            return result and (spokes == static_cast<bike const&>(other).spokes);
        }
    };
    
    int main() {
        car c1("blue");
        car c2("red");
        bike b1(42);
    
        std::cout << std::boolalpha;
        std::cout << c1.compare_to(c2) << "\n"
                  << c1.compare_to(b1) << "\n"
                  << c1.compare_to(c1) << "\n";
    }
    
        enum Kind {
          HUMAN_POWERED  = (0x1 << 0),
          MOTOR_POWERED  = (0x1 << 1),
          BICYCLE        = (0x1 << 2) | HUMAN_POWERED,
          UNICYCLE       = (0x1 << 3) | HUMAN_POWERED,
          CAR            = (0x1 << 4) | MOTOR_POWERED
        };
    
    bool areSameClass (Vehicle const & lhs, Vehicle const & rhs)
    {
      return (lhs->getKind () & rhs->getKind ()) & (HUMAN_POWERED | MOTOR_POWERED);
    }