重载>>基类的运算符

时间:2011-11-27 22:16:30

标签: c++ inheritance

所以我有一个基类Animal,它有两个继承自它的类,它们是猫和狗。这两个课程都重新定义了一种纯粹的虚拟方法,这种方法只会为猫猫咪“喵喵叫”,为狗提供“低音”。在我的主要功能中,我希望能够做到这样的事情:

int main (void) {
  Animal a;
  dog d;

  while (cin  >> a) //is this even possible? would it be cin >> d; instead?
   cout << a << endl;



  return(0);
}

所以这应该让动物说出功能,但我怎么能这样做呢?另外,我很困惑,如果你不知道用户将要使用的动物类型,那么你如何确定使用哪种语音功能,你会使用模板类吗?

4 个答案:

答案 0 :(得分:5)

在基类中执行类似的操作:

#include <istream>

using namespace std;

class Animal
{
  friend istream & operator >> ( istream &is, Animal &animal )
  {
    animal.readFromStream(is);
    return is;
  };
protected:
  virtual void readFromStream( istream &is ) = 0;
};

并在派生中:

class Dog : public Animal
{
  protected:
    virtual void readFromStream( istream &is )
    {
      // read dog
    };
};

答案 1 :(得分:2)

以下是覆盖operator<<的示例,它调用公共成员函数speak()。如果您需要访问重载operator<<中的私人成员,请将其设为friend

#include <iostream>

class Animal {
   public:
      virtual std::string speak(void) = 0;
};

class Dog : public Animal {
   std::string speak() { return "woof"; }
};

class Cat : public Animal {
   std::string speak() { return "meow"; }
};

std::ostream& operator<<(std::ostream& out, Animal& a) {
    out << a.speak();
    return out;
}

int main (void) {
   Dog d;
   Cat c;

   Animal &a = d;
   std::cout << a << std::endl;

   Animal &a2 = c;
   std::cout << a2 << std::endl;

   return 0;
}

您应该能够找出如何对operator>>进行类似操作。

  

另外,我很困惑,如果你不知道用户打算使用的动物类型,那么你如何确定使用哪种说话功能,你会使用模板类吗?

这是动态绑定/多态的背后的想法。 aa2是对Animal的派生类型的引用,由于speak()是虚拟的,因此v表将包含指向必要speak()函数的指针对于DogCat对象。

答案 2 :(得分:1)

你无法准确地做到你想要的。也就是说,你不能

Animal a;
std::cin >> a;

并期望'a'的类型改变。从根本上说,对象不是多态的 - 指针和引用都是多态的。

知道,你可以做一些几乎像你想要的事情:

Animal* pA;
std::cin >> pA;
std::cout << *pA << "\n";
delete pA;

您可以通过重载来实现此目的

istream& operator>>(istream&, Animal*&);

创建(通过new)运行时指示类型的对象。

考虑这个程序:

#include <iostream>
class Animal {
public:
  virtual void speak(std::ostream& os) const = 0;
  virtual ~Animal() {} // must be virtual
};
class Dog : public Animal {
public:
  void speak(std::ostream& os) const { os << "woof"; }
};
class Cat : public Animal {
public:
  void speak(std::ostream& os) const { os << "meow"; }
};
std::ostream& operator<<(std::ostream& os, const Animal& being) {
  being.speak(os);
  return os;
}

std::istream& operator>>(std::istream& is, Animal*& zygote) {
  std::string species;
  is >> species;

  // fetch remainder of line with std::getline()

  if(species == "cat") {
    // parse remainder of line

    // Finally, create a Cat
    zygote = new Cat;
    return is;
  }
  if(species == "dog") {
    // parse remainder of line

    // and create a Dog
    zygote = new Dog;
    return is;
  }

  // Hmm, unknown species? Probably not safe to create
  std::cerr << "Warning! Unknown species. Could be dangerous!\n";
  is.setstate(std::ios::failbit);
  zygote = 0;
  return is;
}

int main () {
  Animal *pPet;

  while(std::cin >> pPet) {
    std::cout << *pPet << "\n";
    delete pPet;
  }
}

答案 3 :(得分:0)

用于&lt;&lt;运营商,有点好吗

friend ostream &operator<<(ostream &output, const Animal & animal)     //output
{
    return output << animal.speak();
} 

对于输入它更复杂,我不知道你是否可以直接用Animal来做 但你可以建立一个AnimalLoader

class AnimalLoader {
    Animal* _animal;

public:
    AnimalLoader() : _animal(NULL) { }

    ~AnimalLoader() { if(_animal) delete _animal; }

    Animal *GetAnimal() 
    {
        Animal *retval = _animal;
        _animal = NULL;
        return retval; 
    }

    friend istream & operator >> ( istream &input, AnimalLoader &animalLoader )
    {
        if(_animal) delete _animal;
        std::string animalStr;
        input >> animalStr;
        if(animalStr == "dog")
            _animal = new Dog();
        else if(animalStr == "cat")
           _animal = new Cat();
        else
           _animal = NULL;

        return input;
    }
};

这样你就可以打电话了

int main (void) {
    AnimalLoader animalLoader;

    while (cin  >> animalLoader) {
        Animal *animal = animalLoader.GetAnimal();
        if(animal != NULL) {
             cout << *animal << endl;
             delete animal;
        }
        else {
             cout << "ERROR: Could not read Animal." << endl;   
        }
    }
    return(0);
}

编辑1 忘了拨打speak()

编辑2 将其应用于OP示例