Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

default constructor & class pointer, overriding, inheritance problem

#include <iostream>

using namespace std;

class Base {
    int x;
public:
        Base() : x() {}
    Base(int x) : x(x) {}
    virtual void print() const {
        cout << x << endl;
    }
};

on Derived(int x, int y) : x(x), y(y) {}, Compiler said must usd "default constructor", but i’d thought that already made, and wonder why default constructor is needed.


class Derived : public Base {
    int x, y;
public:
    Derived(int x, int y) : x(x), y(y) {}
    void print() const override {
        cout << x << ", " << x << endl;
    }
};



int main() {
// All data members of Base and Derived classes must be declared 
// as private access types
    Base* p1 = new Derived(10, 20);     // (x, y)
    Base* p2 = new Base(5);         // (x) 
    p1->print();            // prints 10, 20
    p1->Base::print();      // prints 10
}

second in this problem,

p1->Base::print();      // prints 10

p1->Base::print() must print 10, but it didn’t work. How can I print 10?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

  • Your base class is missing a virtual destructor so trying to delete p1; will cause undefined behavior.
  • Derived has 2 x member variables. Base::x and Derived::x. You most probably only want one. This also explains why p1->Base::print() doesn’t do what you want. Base::x is 0 and Derived::x is 10.
  • Base::x is private so the print function in Derived should probably rely on Base::print to print it.

Example:

The base class here has a virtual destructor and the print function takes an ostream& so that it can print to any ostream (like std::cout or a file stream):

class Base {
    int x;

public:
    Base() : x() {}
    Base(int x) : x(x) {}
    
    virtual ~Base() = default;

    virtual void print(std::ostream& os = std::cout) const {
        os << x; 
    }
};

Derived here does not add an x member variable, but initializes Base with the x value supplied to its constructor. The print function simply calls the base class print:

class Derived : public Base {
    int y;

public:
    Derived(int x, int y) : Base(x), y(y) {}

    void print(std::ostream& os = std::cout) const override {
        Base::print(os); // calls `print` in the base class
        os << ' ' << y;  // and adds its own output
    }
};

You can also add an operator<< overload to make printing easier. Note that you only need one for the base class. It will call the print function in the most derived class:

std::ostream& operator<<(std::ostream& os, const Base& b) {
    b.print(os);
    return os;
}

The main function then becomes:

int main() {
    Base* p1 = new Derived(10, 20);  // (x, y)
    Base* p2 = new Base(5);          // (x)

    std::cout << *p1 << '\n';   // 10 20
    std::cout << *p2 << '\n';   // 5

    p1->Base::print();          // 10

    delete p1;
    delete p2;
}

Or better, use smart pointers so that you don’t forget to delete what you’ve allocated:

int main() {
    std::unique_ptr<Base> p1 = std::make_unique<Derived>(10, 20);
    std::unique_ptr<Base> p2 = std::make_unique<Base>(5);

    std::cout << *p1 << '\n';   // 10 20
    std::cout << *p2 << '\n';   // 5

    p1->Base::print();          // 10
}

Demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading