相关内容:
运行时类型识别
typeid
运算符,返回表达式的类型dynamic_cast
运算符 用于将基类指针或引用安全的转化为派生类的指针或者引用- 当操作被定义为虚函数时,编译器将根据对象的动态类型自动的选择正确的版本 。
- 当
typeid
作用于指针时(而非指针所指的对象),返回的结果是该指针的静态编译时类型。 type_info
类的name
成员函数返回一个C
风格的字符串,表示对象的类型名字。type_info
只能通过typeid
运算符创建。枚举类型
枚举类型使我们可以将一组整形常量组织在一起。枚举值可以不唯一,枚举成员是常量表达式。和类一样,枚举也定义新的类型,也能定义变量。1
enum class 枚举名 { 逗号分隔的枚举列表};
enum
对象赋值必须使用该类型的一个枚举成员,或该类型的另一个对象。类成员指针
成员指针,是指可以指向类的非静态成员的指针。一般情况下,指针指向一个对象,但是成员指针指示的是类的成员。成员指针的类型囊括了类的类型、成员的类型。当初始化一个这样的指针时,我们另其指向类的某个成员,但是不指定该成员所属的对象。直到使用成员指针时,才提供成员所属的对象。嵌套类
一个类可以定义在另一个类的内部,前者称为嵌套类(nested class
) ,后者称为嵌套类型(nested type
)。嵌套类是一个独立的类,与外层基本没有什么关系,特别是,外层类对象和嵌套类对象是相互独立的,嵌套类的对象不能包括任何外层类定义的成员;类似的,在外层类的对象也不能报考任何嵌套类定义的成员。嵌套类的名字在外层作用域内是可见的。之外不可见。 嵌套类对外层类的成员也没有特殊的访问权限。union
一种节省空间的类union
可以定义多个数据成员,但在任何时刻,只有一个数据成员可以有值。union
可以定义包括构造函数和析构函数在内的成员函数。但union
不能继承自其它类,也不能作为基类使用。 不能有虚函数。代码相关内容:
show.c
:1
2
3
4
5
6
void show(const char * msg)
{
printf("%s\n", msg);
}main.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
109
110
111
112
using namespace std;
class Item_base
{
public:
virtual double net_price(size_t n) const
{
//局部类,就是类位于函数中,用也只能在函数中用;
class Cat
{
};
Cat cat;
return n * price;
}
class Dog
{
};
public:
std::string isbn;
protected:
double price;
};
class Bulk_item : public Item_base
{
public:
double net_price(std::size_t cnt) const
{
if (cnt > min_qty)
return cnt * (1 - discount) * price;
else
return cnt * price;
}
private:
std::size_t min_qty;
double discount;
};
//实际上char ,int ,double占用的是同一块内存,使用其中最大的(也就是double:8个字节)
union TokenValue
{
char cval;
int ival;
double dval;
};
//位域 一般使用无符号整型来创建
typedef unsigned int Bit; // 整型:4个字节,32位
class File{ //位域类
public:
Bit mode : 2; //使用2位给mode;
Bit modified : 1;
Bit prot_owner : 3;
Bit prot_group : 3;
Bit prot_world : 3;
// ...
};
enum { READ = 01, WRITE = 02 };
//extern "C"来调用外部的C程序;
extern "C" void show(const char *);
int main()
{
show("hello extern \"C\"\n");
Item_base *pItem = new Item_base(); //使用new操作符创建对象;来分配对象所用的内存;
allocator<Item_base> a; //使用allocator来创建对象,分配内存;
a.allocate(100); //分配的内存大小指定为100;
//RTTI : 运行时对象类型识别,主要用在不能使用虚函数的时候;
Item_base *bp = new Item_base();
Bulk_item *dp = new Bulk_item();
Item_base *bp2 = dp; //正确;将派生类对象转换为基类对象,向上转型,是允许的;
//Bulk_item *dp2 = bp; //错误;将基类对象转换为派生类对象,这么做是不允许的;
Bulk_item *dp2 = dynamic_cast<Bulk_item*>(bp);//如果想将基类对象转换为派生类对象,可以使用动态类型变换,dynamic_cast属于RTTI的一种;
if (typeid(Bulk_item) == typeid(*dp)) cout << "Bulk_item类型" << endl;
cout << typeid(*bp).name() << endl; //可以将类名输出;属于RTTI,运行时类型识别;
cout << typeid(*dp).name() << endl; //可以将类名输出;属于RTTI,运行时类型识别;
//类成员指针
//std::string Item_base ::* p = &Item_base.isbn; //字符串指针;
double(Item_base::* pmf)(std::size_t) const = &Item_base::net_price; //函数指针;
//嵌套类
Item_base::Dog dog;
//虽然之后a,但是调用的时候返回的是a对应的ASCII码97;
TokenValue myToken = { 'a' };
cout << myToken.ival << endl;
File myFile; //使用位域非常节省内存;
myFile.mode = WRITE;
myFile.modified = 1;
int x;
volatile int y; //加上volatile表示是易失的;加上volatile实际上是告诉c++不要对变量y进行优化(c++会对默认对程序进行优化,优化的时候会改变在内存中的位置);
return 0;
}代码执行结果:
参考链接:
C2664 “void test(char *)”: 无法将参数 1 从“const char [12]”转换为“char *”
第 19 章 特殊工具与技术