RandomCPlusPlus
RandomCPlusPlus

Reputation: 359

Virtual Functions in Class Hierarchy

I suppose it is not such a clever question but i have been spending considerable time on it and still doesnt compile

Can you please explain why?

Thanks

1>------ Build started: Project: Ch17, Configuration: Release Win32 ------
1>  p731.cpp
1>\\na-13\agnolucp\my documents\visual studio 2010\projects\ch17\ch17\Bear.h(29): error     C2084: function 'std::ostream &Bear::print(std::ostream &) const' already has a body
1>          \\na-13\agnolucp\my documents\visual studio 2010\projects\ch17\ch17\Bear.h(19) : see previous definition of 'print'
1>p731.cpp(16): error C2264: 'Bear::print' : error in function definition or declaration; function not called
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

//Endangered

#ifndef ENDAGERED
#define ENDAGERED
#include <iostream>


class Endangered {
public:
     //virtual ~Endangered();
     virtual std::ostream& print(std::ostream&) const;
     // virtual so needs to be defined otherwise error
     virtual void highlight() const;
};

//ZooAnimal

#ifndef ZOOANIMAL
#define ZOOANIMAL
#include<string>
class ZooAnimal {
public:
    ZooAnimal();
    ZooAnimal(std::string animal, bool exhibit,
              std::string family): Name(animal), 
                                   OnExhibition(exhibit), 
                                   FamilyName(family) { } 
    //virtual ~ZooAnimal();

    virtual std::ostream& print(std::ostream&) const;

    // accessors
    std::string getName() const { return Name; }
    std::string getFamilyName() const { return FamilyName; }
    bool getOnExhibition() const { return OnExhibition; }
    // ...
protected:
    std::string Name;
    bool        OnExhibition;
    std::string FamilyName;
    // ...
private:
};

std::ostream& ZooAnimal::print(std::ostream &out) const {
    return out << "I am printing ZooAnimal" << std:: endl;
}




#endif




void Endangered::highlight() const {
    std::cout << "HIGHLIGHT: HEY, I AM IN DANGER" << std::endl;
}


std::ostream& Endangered::print( std::ostream &out ) const {
    // thsi would be fine
    // return out << "I Aa Printing Endangered" << std::endl;
    out << "I Aa Printing Endangered" << std::endl;
    return out;
}


#endif

// Bear

#ifndef BEAR
#define BEAR

#include "ZooAnimal.h"
#include <iostream>

class Bear : public ZooAnimal {
enum DanceType { two_left_feet, macarena, fandango, waltz };
public:
    Bear();
    //listing all arguments
    // passing BaseClass constructor in initialiser list
    Bear(std::string name, bool onExhibit=true, 
         std::string family = "Bear"):
              ZooAnimal(name, onExhibit, family),
              ival(0), dancetype(macarena) { }

    virtual std::ostream& print(std::ostream&) const;
    void dance() const;

    //virtual ~Bear();
private:
    int         ival;
    DanceType   dancetype;
};
#endif

std::ostream& Bear::print(std::ostream &out) const {
    return out << "I am printing Bear" << std:: endl;
}

// panda

#ifndef PANDA
#define PANDA

#include <iostream> 
#include "Bear.h"
#include"Endangered.h"

class Panda : public Bear, public Endangered {
public:
    Panda();
    Panda(std::string name, bool onExhibit=true);
    // virtual ~Panda();
    // mentioning virtual would not be necessary
    virtual std::ostream& print(std::ostream&) const;
    // mentioning virtual would not be necessary
    virtual void highlight() const  {
        std::cout << "HIGHLIGHT: Hey I am Panda" <<std::endl;
    }
};


std::ostream& Panda::print(std::ostream &out ) const {
    // this would be fine
    // return out << " I am printing Pandaa" << std::endl;
    out << "I am printing Panda" << std::endl;
    return out;

}


Panda::Panda(std::string name, bool onExhibit)
        : Bear(name, onExhibit, "Panda") { }

void Bear::dance() const {
    switch(dancetype) {
        case two_left_feet: 
            std::cout << "I am doing two_left_feet"<< std::endl;
            break; 
        case macarena:  
            std::cout << "I am doing macarena"<< std::endl;
            break; 
        case fandango: 
            std::cout << "I am doing fandango"<< std::endl;     
            break;          
        case waltz: 
            std::cout << "I am doing waltz"<< std::endl;
            break; 
    }
}


# endif

// mian

#include "Bear.h"
#include "Panda.h"
#include "ZooAnimal.h"

#include<iostream>
#include<string>

int main () {

    Endangered a; 
    ZooAnimal b("John", true, "DiMonte");
    //b.print(std::cout);
    Bear c("Luigi");
    c.dance();
    c.print(std::cout);
    Panda d("Luigi");
    d.print(std::cout);
    d.highlight();
    d.dance();
    Panda e();
}

Upvotes: 0

Views: 461

Answers (2)

Zuljin
Zuljin

Reputation: 2640

In main.cpp you firstly included Bear.h and this file contains definition of std::ostream& Bear::print(std::ostream &out). This definition is not guarded by

#ifndef BEAR
#define BEAR 
...
#endif

Second include in main is Panda.h and in Panda.h you once again include Bear.h. And because you don't guard Bear::print it is included second time and compiler fails because it doesn't know which method definition it should use.

To reduce occurrence of such errors you should include only declaration in your *.h files while all definitions should go to *.cpp

Upvotes: 1

RandomCPlusPlus
RandomCPlusPlus

Reputation: 359

Ok the stupid answer is that you need to get rid of

//#include "Bear.h" in Panda.

so my question is now - why? - why dont I need to include #include "Bear.h" as Bear is part of my inheritance hierarchy? I thought the compiler needed to see the definition.

Upvotes: 0

Related Questions