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;
}
回答:
クリックして回答を表示
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();
}
回答:
クリックして回答を表示
121説明:
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();
}
回答:
クリックして回答を表示
AAABBAAB説明:
C *const p1 では、p1 ポインターが const 修飾されているため、s オブジェクトのメンバ変数 p1 を呼び出すときには const バージョンの foo が呼び出される。C const *p2 では、*p(C クラス)オブジェクトが const 修飾されているため、s オブジェクトのメンバ変数 p2 を呼び出すときには const バージョンの foo が呼び出される。
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]>;
}
回答:
クリックして回答を表示
0110001説明:
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] は 2 次元配列で、要素は定数ですので、結果は true です。