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:
即使 A::foo() 是虚函数,但在构造和析构的过程中不会被认为是虚拟的。
在构造 B 之前应该构造 A,而在构造 A 的期间,B 尚未构造,所以不应该被使用,A::A() 中的 foo() 调用的自然是 A::foo()。
在对象 b 销毁时,也面临同样的问题,因为先调用 B 的析构,然后再调用 A 的析构,在对象 b 析构后,B::foo() 也是不应该被使用的。
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 修饰 p1 指针,所以 s 对象的成员变量 p1 调用 foo 时会使用非 const 版本,C const *p2 中 const 修饰 *p(C 类)对象,所以 s 对象的成员变量 p2 调用 foo 时会使用会使用 const 版本。
r 是对象 s 的常量引用,const 改变了成员 v 的行为,因为 std::vector 对 operator[] 进行了重载,常量对象调用是返回常量引用的版本,返回的也是常量引用,因此调用 foo 是 const 版本。
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 * 是一个指向常量整数的指针,即常量指针,虽然指针指向的内容是常量,但是指针本身不是常量,所以结果为 false。
int *const 是一个指针常量,指针本身是常量,所以结果为 true。
const int[1] 是一个包含常量整数的数组,数组的元素是常量,所以结果为 true。
const int ** 是一个指向 指向常量指针 的指针((const int *) *ptr),指针本身不是常量,所以结果为 false。
int *const * 是一个指向 指向指针常量 的指针((int *const) *ptr),指针本身不是常量,所以结果为 false。
const int (*)[1] 是一个指向包含 常量数组 的指针,指针本身并不是常量,所以结果为 false。
const int *[1] 是一个包含指向 常量指针 的数组(const int *ptr[1]),数组元素是常量指针,所以结果为 false。
const int[1][1] 是一个二维数组,其中的元素是常量,所以结果是 true。