#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 todelete p1;
will cause undefined behavior. Derived
has 2x
member variables.Base::x
andDerived::x
. You most probably only want one. This also explains whyp1->Base::print()
doesn't do what you want.Base::x
is0
andDerived::x
is10
.Base::x
isprivate
so theprint
function inDerived
should probably rely onBase::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
}