基本数据类型

基本数据类型

在 C++ 中,基本数据类型是构建程序的基石。我们将讨论以下几种基本数据类型:intfloatdoublecharbool。每种数据类型的特性和用途都稍有不同。

1. 整数类型 (int)

int 是用于表示整数的基本数据类型。它可以存储正整数、负整数以及零。根据平台的不同,int 的大小一般是 4 字节(32 位)。

1.1 使用示例

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;

int main() {
int a = 10; // 定义一个整数变量 a
int b = -5; // 定义一个负整数变量 b
cout << "a = " << a << ", b = " << b << endl; // 输出变量 a 和 b 的值
return 0;
}

2. 浮点类型 (floatdouble)

floatdouble 用于表示带小数点的数值。它们的区别在于精度和所占内存的大小。

2.1 float

float 是单精度浮点数,通常占用 4 字节(32 位),可以存储约 7 位有效数字。

2.1.1 使用示例

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main() {
float pi = 3.14f; // 定义一个 float 类型的变量
cout << "pi = " << pi << endl; // 输出变量 pi 的值
return 0;
}

2.2 double

double 是双精度浮点数,通常占用 8 字节(64 位),可以存储约 15 位有效数字。

2.2.1 使用示例

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main() {
double e = 2.718281828459; // 定义一个 double 类型的变量
cout << "e = " << e << endl; // 输出变量 e 的值
return 0;
}

3. 字符类型 (char)

char 用于表示单个字符,通常占用 1 字节(8 位)。它可以存储 ASCII 字符集中的字符(如字母、数字和符号)。

3.1 使用示例

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main() {
char grade = 'A'; // 定义一个 char 类型的变量
cout << "Grade = " << grade << endl; // 输出变量 grade 的值
return 0;
}

4. 布尔类型 (bool)

bool 用于表示逻辑值。它只有两个可能的值:true(真)和 false(假)。通常占用 1 字节(8 位)。

4.1 使用示例

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main() {
bool isEven = true; // 定义一个 bool 类型的变量
cout << "Is number even? " << isEven << endl; // 输出布尔变量的值
return 0;
}

5. 小结

在 C++ 中,基本数据类型提供了多种方式来存储和处理数据。理解这些数据类型的特性以及如何使用它们是编程的基础。接下来,我们将学习如何使用这些数据类型进行更加复杂的操作和控制流。

9 C++ 进阶实战教程

9 C++ 进阶实战教程

小节:模板函数与模板类

1. 什么是模板

在C++中,模板是一种强大的特性,允许我们编写与类型无关的代码。通过使用模板,我们可以创建函数模板类模板,提高代码的重用性和灵活性。

2. 模板函数

2.1. 定义模板函数

模板函数是指可以接受不同数据类型作为参数的函数。通过template关键字来定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

// 定义模板函数
template <typename T>
T add(T a, T b) {
return a + b;
}

int main() {
cout << "Int addition: " << add<int>(3, 5) << endl; // 输出 Int addition: 8
cout << "Double addition: " << add<double>(3.5, 2.5) << endl; // 输出 Double addition: 6
return 0;
}

2.2. 模板函数的特点

  • 类型参数:可以使用typenameclass关键字来定义类型参数。
  • 自动推导:在调用模板函数时,如果不指定类型参数,编译器会根据参数类型自动推导。

3. 模板类

3.1. 定义模板类

模板类是指可以处理不同数据类型的类。与模板函数类似,也使用template关键字定义。

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
#include <iostream>
using namespace std;

// 定义模板类
template <typename T>
class Box {
private:
T value;
public:
Box(T v) : value(v) {}

T getValue() const {
return value;
}
};

int main() {
Box<int> intBox(123);
Box<double> doubleBox(456.78);

cout << "Int Box: " << intBox.getValue() << endl; // 输出 Int Box: 123
cout << "Double Box: " << doubleBox.getValue() << endl; // 输出 Double Box: 456.78

return 0;
}

3.2. 模板类的特点

  • 多种类型:模板类允许在实例化时指定不同的类型。
  • 成员函数也可以是模板:模板类的成员函数也可以是模板。

4. 使用模板的注意事项

  • 编译时类型检查:模板的类型检查是在编译时进行的,因此在使用过程中如类型不匹配会导致编译错误。
  • 代码膨胀:每一种类型的模板实例化都会生成新的函数或类。

5. 实际案例

以下是一个结合模板函数与模板类的完整示例:

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
#include <iostream>
#include <vector>
using namespace std;

// 模板函数:返回容器的最大值
template <typename T>
T getMax(const vector<T>& elements) {
T maxElement = elements[0];
for (const auto& elem : elements) {
if (elem > maxElement) {
maxElement = elem;
}
}
return maxElement;
}

// 模板类:通用栈
template <typename T>
class Stack {
private:
vector<T> elements;
public:
void push(const T& element) {
elements.push_back(element);
}

void pop() {
elements.pop_back();
}

T top() const {
return elements.back();
}

bool isEmpty() const {
return elements.empty();
}
};

int main() {
// 测试模板函数
vector<int> intVec = {1, 2, 3, 4, 5};
cout << "Max element in intVec: " << getMax(intVec) << endl; // 输出 5

// 测试模板类
Stack<string> stringStack;
stringStack.push("Hello");
stringStack.push("World");

cout << "Top element in stringStack: " << stringStack.top() << endl; // 输出 World

return 0;
}

6. 总结

模板是C++中重要的编程概念,通过模板函数模板类可以实现代码的高效重用。掌握它们将使我们的编程更加灵活且可维护。

类型转换与类型检查

类型转换与类型检查

在C++中,类型是一个非常重要的概念。在编程中,我们经常需要进行类型转换,以便在不同类型之间进行操作。本节将详细介绍C++中的类型转换和类型检查机制。

1. 类型转换

类型转换是将一种数据类型的值转换为另一种数据类型的过程。在C++中,类型转换可以分为几种主要形式:

1.1 隐式类型转换

隐式类型转换(也称为自动类型转换)是指编译器在需要时自动进行的类型转换。例如,当将一个int类型赋值给一个double类型的变量时,编译器会自动将int转换为double

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;

int main() {
int intValue = 10;
double doubleValue = intValue; // 隐式转换
cout << "intValue: " << intValue << endl;
cout << "doubleValue: " << doubleValue << endl; // 输出 10.0
return 0;
}

1.2 显式类型转换

显式类型转换(也称为强制类型转换)是程序员使用转换运算符主动指定的类型转换。C++提供了几种显式转换的方式:

1.2.1 C风格转换

C风格的转换直接在括号内指定目标类型。

1
2
3
float floatValue = 3.14;
int intValue = (int)floatValue; // C风格转换
cout << "intValue: " << intValue << endl; // 输出 3

1.2.2 static_cast

static_cast是C++中更安全的类型转换方式,通常用于数值类型之间的转换。

1
2
3
double doubleValue = 9.7;
int intValue = static_cast<int>(doubleValue); // 使用 static_cast
cout << "intValue: " << intValue << endl; // 输出 9

1.2.3 dynamic_cast

dynamic_cast主要用于进行类层次结构中的安全类型转换,常用于将基类指针或引用转换为派生类指针或引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Base {
public:
virtual void show() { cout << "Base class" << endl; }
};

class Derived : public Base {
public:
void show() override { cout << "Derived class" << endl; }
};

void example(Base* basePtr) {
if (Derived* derivedPtr = dynamic_cast<Derived*>(basePtr)) {
derivedPtr->show(); // 安全转换,执行 Derived 的 show
} else {
cout << "Conversion failed!" << endl;
}
}

1.2.4 const_cast

const_cast用于移除对象的常量性,允许你修改一个constvolatile对象。

1
2
3
const int a = 10;
int* b = const_cast<int*>(&a);
*b = 20; // 修改 a 的值,尽管这样做是未定义行为

1.2.5 reinterpret_cast

reinterpret_cast用于进行低级别的类型转换,通常用于指针类型之间的转换。

1
2
long address = 0x12345678;
int* p = reinterpret_cast<int*>(address); // 将长整型转换为指针类型

1.3 类型转换的注意事项

在使用类型转换时,要注意以下几个方面:

  • 数据丢失:隐式转换可能会导致数据丢失,比如将double转换为int,小数部分会被截断。
  • 类型安全性:使用static_castdynamic_cast等方式进行安全转换,可以避免潜在的类型错误。
  • 未定义行为:某些强制转换(如const_cast)可能会导致未定义行为,需谨慎使用。

2. 类型检查

C++中对于类型的检查主要是在编译时进行的,但有时也会在运行时进行。

2.1 使用 typeid

C++提供了typeid操作符,可以检查对象的动态类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <typeinfo>
using namespace std;

class Base {
public:
virtual ~Base() {}
};

class Derived : public Base {};

int main() {
Base* b = new Derived();
cout << "The type of b is: " << typeid(*b).name() << endl; // 输出 Derived 的类型名
delete b;
return 0;
}

2.2 使用 RTTI(运行时类型识别)

C++的RTTI允许程序员在运行时获取对象的信息,例如可以使用dynamic_cast来验证指针的类型。

2.3 自定义类型检查

在某些情况下,可以通过自定义函数检查类型。例如,可以重载operator==来确定自定义对象的类型。

小结

本节介绍了C++中类型转换与类型检查的主要概念。理解各类型转换方式的特点及使用场景,对于提高编程能力和代码的安全性至关重要。在编程实践中,合理选择和使用这些转换方式,将帮助你编写出更加健壮和安全的代码。