Home > Blockchain >  default constructor & class pointer, overriding, inheritance problem
default constructor & class pointer, overriding, inheritance problem

Time:12-06

#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?

CodePudding user response:

  • 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

  • Related