Q027#
#include <iostream>
struct A {
virtual std::ostream &put(std::ostream &o) const {
return o << 'A';
}
};
struct B : A {
virtual std::ostream &put(std::ostream &o) const override {
return o << 'B';
}
};
std::ostream &operator<<(std::ostream &o, const A &a) {
return a.put(o);
}
int main() {
B b;
std::cout << b;
}
Answer:
click to see answer
BQ029#
#include <iostream>
struct A {
A() {
// std::cout << "A::A()" << std::endl;
foo();
}
virtual ~A() {
// std::cout << "A::~A()" << std::endl;
foo();
}
virtual void foo() {
// std::cout << "A::foo()" << std::endl;
std::cout << "1";
}
void bar() {
// std::cout << "A::bar()" << std::endl;
foo();
}
};
struct B : public A {
virtual void foo() {
// std::cout << "B::foo()" << std::endl;
std::cout << "2";
}
};
int main() {
B b;
b.bar();
}
Answer:
click to see answer
121Explain:
Even though A::foo()
is a virtual function, it is not considered virtual during construction and destruction.
Before constructing B, A should be constructed, and during the construction of A, B is not yet constructed, so it should not be used, the foo()
called in A::A()
naturally calls A::foo()
.
When the object b
is destroyed, the same problem arises because B's destructor is called first, followed by A's destructor, and after the object b
is destroyed, B::foo()
should not be used.
Q114#
#include <iostream>
#include <memory>
#include <vector>
class C {
public:
void foo() {
std::cout << "A";
}
void foo() const {
std::cout << "B";
}
};
struct S {
std::vector<C> v;
std::unique_ptr<C> u;
C *const p1;
C const *p2;
S() : v(1)
, u(new C())
, p1(u.get()
, p2(u.get()) {
}
};
int main() {
S s;
s.v[0].foo();
s.u->foo();
s.p1->foo();
s.p2->foo();
const S &r = s;
r.v[0].foo();
r.u->foo();
r.p1->foo();
r.p2->foo();
}
Answer:
click to see answer
AAABBAABExplain:
C *const p1
const modifies the p1
pointer, so when foo
is called on the member variable p1
of object s
, the non-const version of foo
will be used. C const *p2
const modifies the *p
(C object), so when foo
is called on the member variable p2
of object s
, the const version of foo
will be used.
r
is a constant reference to object s
, and const
changes the behavior of member v
because std::vector
overloads operator[]
and the version called by a constant object returns a constant reference, so the returned value is also a constant reference, so calling foo
will use the const version.
Q360#
// using C++17
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::is_const_v<const int *>;
std::cout << std::is_const_v<int *const>;
std::cout << std::is_const_v<const int[1]>;
std::cout << std::is_const_v<const int **>;
std::cout << std::is_const_v<int *const *>;
std::cout << std::is_const_v<const int(*)[1]>;
std::cout << std::is_const_v<const int *[1]>;
std::cout << std::is_const_v<const int[1][1]>;
}
Answer:
click to see answer
0110001Explain:
const int *
is a pointer to a constant integer, which means a constant pointer, although the content pointed to by the pointer is constant, the pointer itself is not constant, so the result is false
.
int *const
is a constant pointer, the pointer itself is constant, so the result is true
.
const int[1]
is an array containing constant integers, the elements of the array are constants, so the result is true
.
const int **
is a pointer to a pointer to a constant pointer ( (const int *) *ptr
), the pointer itself is not constant, so the result is false
.
int *const *
is a pointer to a constant pointer ( (int *const) *ptr
), the pointer itself is not constant, so the result is false
.
const int (*)[1]
is a pointer to an array of constant integers, the pointer itself is not constant, so the result is false
.
const int *[1]
is an array of pointers to constant integers ( const int *ptr[1]
), the elements of the array are constant pointers, so the result is false
.
const int[1][1]
is a two-dimensional array, the elements of which are constants, so the result is true
.