-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathCastingSample.cpp
108 lines (89 loc) · 3.08 KB
/
CastingSample.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <iostream>
#include <ostream>
#include <typeinfo>
#include "../pchar.h"
using namespace std;
class A {
public:
A(void) : m_value(0) {}
virtual ~A(void) {}
virtual int GetValue(void) { return m_value; }
virtual void SetValue(int value) { m_value = value; }
private:
int m_value;
};
class B : virtual public A {
public:
B(void) : A() {}
virtual ~B(void) {}
virtual int GetValue(void) override { return A::GetValue(); }
virtual void SetValue(int value) { A::SetValue(-value); }
};
class C {
public:
C(void) {}
~C(void) {}
};
int _pmain(int /*argc*/, _pchar* /*argv*/[]) {
A a1;
B b1;
C c1;
A* p_a1 = &a1;
B* p_b1 = &b1;
// Неявное приведение типа объекта B к указателю на A:
A* p_ab1 = &b1;
A& r_ab1 = b1;
// static_cast не может привести тип через виртуальное наследование:
// B& b1Ref = static_cast<B&>(*p_ab1);
// А dynamic_cast может:
B& b1Ref = dynamic_cast<B&>(*p_ab1);
try {
B& b2Ref = dynamic_cast<B&>(*p_a1);
} catch (bad_cast) {
// Нельзя привести тип к производному классу, если этот экземпляр
// фактически не принадлежит к производному классу или какому-нибудь
// классу производному от него.
wcout << L"You can't cast to a derived class if it isn't "
<< L"actually an instance of that derived class or of some "
<< L"class derived from it." << endl;
}
// ВЫВОД:
// You can't cast to a derived class
// if it isn't actually an instance of that derived class
// or of some class derived from it.
A& a1Ref = static_cast<A&>(*p_b1);
A* a1Ptr = dynamic_cast<A*>(p_b1);
A* dcBPtrToAPtr = dynamic_cast<A*>(p_b1);
// Why oh why does it let you do this?
B* dcAPtrToBPtr = dynamic_cast<B*>(p_a1);
C* p_aPtrToCPtr = nullptr;
// Это приведение типа вернёт null, поэтому если нужно исключение, то бросать
// его надо самостоятельно:
try {
p_aPtrToCPtr = dynamic_cast<C*>(p_a1);
if (p_aPtrToCPtr == nullptr) { throw bad_cast(); }
} catch (std::bad_cast) {
wcout << L"Bad cast!" << endl;
}
// ВЫВОД:
// Bad cast!
// Приведёт к runtime-исключению:
try {
C& r_aPtrToCPtr= dynamic_cast<C&>(a1Ref);
} catch (std::bad_cast) {
wcout << L"Bad cast!" << endl;
}
// ВЫВОД:
// Bad cast!
// Const cast для добавления const (это ОК):
auto p_a2 = const_cast<const A*>(p_a1);
// Недопустимо из-за константности:
// p_a2->SetValue(20);
// Const cast для удаления const (плохая идея):
auto p_a3 = const_cast<A*>(p_a2);
// Допустимо сейчас, т.к. мы удалили const:
p_a3->SetValue(20);
// Приведение типа в стиле C. Не следует так делать:
A* cCast = (A*)p_b1;
return 0;
}