#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?
>Solution :
- Your base class is missing a
virtualdestructor so trying todelete p1;will cause undefined behavior. Derivedhas 2xmember variables.Base::xandDerived::x. You most probably only want one. This also explains whyp1->Base::print()doesn’t do what you want.Base::xis0andDerived::xis10.Base::xisprivateso theprintfunction inDerivedshould probably rely onBase::printto 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
}