C++1d1C到C++
C++基础:1d1C到C++
[TOC]
1 C到C++
1.1 缺省函数参数
在C++中,缺省函数参数(Default Function Arguments)允许你在定义函数时为某些参数指定默认值。如果调用函数时没有为这些参数提供值,编译器会自动使用默认值。这使得函数调用更加灵活,减少了需要编写的重载函数数量。
在函数声明或定义中,可以为参数指定默认值。语法如下:
1 | 返回类型 函数名(参数类型 参数名 = 默认值); |
以下是一个简单的示例,展示了如何使用缺省函数参数:
1 |
|
1 | Hello, World! |
1.1.1 注意事项
顺序:缺省参数必须从右向左依次指定。也就是说,如果一个参数有默认值,那么它右边的所有参数也必须有默认值。
1
2void func(int a, int b = 10, int c = 20); // 合法
void func(int a = 10, int b, int c = 20); // 非法声明与定义:如果函数在声明时指定了缺省参数,那么在定义时不应再指定缺省参数,否则会导致编译错误。
1
2
3
4
5
6
7// 声明
void func(int a = 10);
// 定义
void func(int a) {
// 函数体
}重载函数:缺省参数可以与函数重载一起使用,但需要注意避免歧义。
1
2void func(int a);
void func(int a, int b = 10); // 可能导致歧义指针和引用:缺省参数可以是常量、变量、表达式、函数调用等,但不能是局部变量。
1
2int globalVar = 10;
void func(int a = globalVar); // 合法
1.2 函数重载
在C++中,函数重载(Function Overloading) 允许你在同一个作用域内定义多个同名函数,只要它们的参数列表(参数的类型、数量或顺序)不同即可。函数重载是C++支持多态性的一种方式,它使得你可以用同一个函数名处理不同类型或数量的输入。
- 函数名相同:重载的函数必须具有相同的名称。
- 参数列表不同:重载函数的参数列表必须在以下至少一个方面有所不同:
- 参数的类型
- 参数的数量
- 参数的顺序(如果类型不同)
- 返回类型不影响重载:仅返回类型不同不足以构成函数重载。
以下是一个简单的函数重载示例:
1 |
|
1 | Integer: 10 |
1.2.1 函数重载的工作原理
当调用一个重载函数时,编译器会根据以下规则确定调用哪个函数:
- 精确匹配:如果参数类型完全匹配,则调用对应的函数。
- 类型转换:如果没有精确匹配,编译器会尝试进行隐式类型转换(如
int
到double
),并调用最合适的函数。 - 歧义检测(二异性问题):如果存在多个可能的匹配,或者没有匹配的函数,编译器会报错。
1.2.2 注意事项
返回类型不影响重载:
1
2int func(int a);
double func(int a); // 错误:仅返回类型不同,不能构成重载默认参数可能导致歧义:
1
2
3
4void func(int a);
void func(int a, int b = 10);
func(5); // 歧义:编译器无法确定调用哪个函数作用域规则:
- 如果在一个作用域内定义了重载函数,而在另一个作用域内定义了同名函数,则后者会隐藏前者。
- 例如,在类中定义的重载函数会隐藏全局作用域中的同名函数。
重载与模板:
- 函数模板也可以与重载结合使用,但需要确保模板实例化后不会导致歧义。
1.3 命名空间
在C++中,命名空间(Namespace) 是一种用于组织代码的机制,它可以避免命名冲突,尤其是在大型项目或使用多个第三方库时。命名空间将全局作用域划分为不同的区域,每个区域内的标识符(如变量、函数、类等)具有唯一性,但在不同命名空间中可以存在同名的标识符。
- 避免命名冲突:不同命名空间中的同名标识符不会冲突。
- 组织代码:将相关的代码组织在一起,提高代码的可读性和可维护性。
- 支持模块化编程:命名空间可以将代码划分为逻辑模块。
1.3.1 定义命名空间
使用 namespace
关键字定义命名空间:
1 | namespace 命名空间名 { |
示例:
1 | namespace MyNamespace { |
1.3.2 访问命名空间中的成员
使用作用域解析运算符 ::
访问命名空间中的成员:
1 | 命名空间名::成员名 |
示例:
1 | int main() { |
1.3.3 命名空间的嵌套
命名空间可以嵌套定义,形成层次化的结构:
1 | namespace Outer { |
访问嵌套命名空间中的成员:
1 | int main() { |
1.3.4 使用 using
指令
为了避免每次访问命名空间成员时都写完整的命名空间路径,可以使用 using
指令。
1.3.4.1 . using namespace
指令
引入整个命名空间,使得该命名空间中的所有成员可以直接使用:
1 | using namespace 命名空间名; |
示例:
1 | using namespace MyNamespace; |
1.3.4.2 . using
声明
引入命名空间中的特定成员,使得该成员可以直接使用:
1 | using 命名空间名::成员名; |
示例:
1 | using MyNamespace::value; |
1.3.5 匿名命名空间
匿名命名空间是一个没有名字的命名空间,其成员的作用域仅限于当前文件(类似于 static
关键字的作用)。
示例:
1 | namespace { |
1.3.6 命名空间与全局作用域
如果命名空间中的成员与全局作用域中的成员同名,可以通过 ::
访问全局作用域的成员:
1 | int value = 40; |
1.3.7 命名空间的别名
如果命名空间的名字太长,可以为其定义别名:
1 | namespace 别名 = 命名空间名; |
示例:
1 | namespace VeryLongNamespaceName { |
1.3.8 标准命名空间 std
C++ 标准库中的所有内容都定义在 std
命名空间中。例如:
1 | std::cout |
通常使用 using namespace std;
来简化代码,但在大型项目中应避免全局引入 std
,以防止命名冲突。
1.3.9 总结
命名空间是C++中用于组织代码、避免命名冲突的重要机制。通过合理使用命名空间,可以提高代码的可读性、可维护性和模块化程度。以下是命名空间的核心要点:
- 使用
namespace
定义命名空间。 - 使用
::
访问命名空间成员。 - 使用
using
指令简化命名空间成员的访问。 - 匿名命名空间用于限制作用域。
- 命名空间可以嵌套和定义别名。
1.4 标准数据流
在C++中,标准输入输出流 是通过 流(Stream) 机制实现的,它提供了一种方便的方式来处理输入和输出操作。C++ 标准库中的 <iostream>
头文件定义了用于标准输入输出的流类,主要包括:
std::cin
:标准输入流(通常与键盘输入关联)。std::cout
:标准输出流(通常与控制台输出关联)。std::cerr
:标准错误流(无缓冲,通常用于错误信息)。std::clog
:标准日志流(有缓冲,通常用于日志信息)。
1.4.1 标准输出流 (std::cout
)
std::cout
是用于将数据输出到控制台的流对象。它通常与插入运算符 <<
一起使用。
1 |
|
1 | Hello, World! |
说明:
<<
是插入运算符,用于将数据插入到输出流中。std::endl
用于插入换行符并刷新输出缓冲区。
1.4.2 标准输入流 (std::cin
)
std::cin
是用于从控制台读取输入的流对象。它通常与提取运算符 >>
一起使用。
示例:
1 |
|
输出:
1 | Enter a number: 42 |
说明:
>>
是提取运算符,用于从输入流中提取数据。std::cin
会自动跳过空白字符(如空格、制表符和换行符)。
1.4.3 标准错误流 (std::cerr
)
std::cerr
是用于输出错误信息的流对象。它与 std::cout
类似,但通常是无缓冲的,这意味着错误信息会立即输出。
示例:
1 |
|
输出:
1 | An error occurred! |
1.4.4 标准日志流 (std::clog
)
std::clog
是用于输出日志信息的流对象。它与 std::cerr
类似,但通常是有缓冲的。
示例:
1 |
|
输出:
1 | This is a log message. |
1.4.5 格式化输出
C++ 提供了多种方式格式化输出,例如设置宽度、精度、填充字符等。
1.4.6 设置宽度和填充字符
使用 std::setw
和 std::setfill
设置输出宽度和填充字符。
示例:
1 |
|
输出:
1 | ********42 |
1.4.7 设置浮点数精度
使用 std::setprecision
设置浮点数的输出精度。
示例:
1 |
|
输出:
1 | 3.142 |
1.4.8 处理输入错误
在使用 std::cin
时,可能会遇到输入错误(例如输入类型不匹配)。可以通过检查流的状态来处理错误。
示例:
1 |
|
1.5 std::string
类
在C++中,std::string
是一个用于表示和操作字符串的类,定义在 <string>
头文件中。它是C++标准库的一部分,提供了丰富的功能来处理字符串,比C语言中的字符数组(char[]
)更加安全和方便。
1.5.1 std::string
的基本特性
- 动态大小:
std::string
可以动态调整其大小,无需手动管理内存。 - 丰富的成员函数:提供了大量的成员函数来操作字符串,如查找、替换、插入、删除等。
- 支持运算符重载:可以使用
+
、==
、!=
等运算符来操作字符串。 - 安全性:自动处理内存分配和释放,避免了缓冲区溢出等问题。
1.5.2 创建和初始化 std::string
std::string
可以通过多种方式创建和初始化:
- 默认构造函数
1 | std::string str; |
- 使用C风格字符串初始化
1 | std::string str = "Hello, World!"; |
- 使用部分字符初始化
1 | std::string str("Hello, World!", 5); // 只取前5个字符:"Hello" |
- 使用重复字符初始化
1 | std::string str(5, 'A'); // 创建包含5个'A'的字符串:"AAAAA" |
- 使用另一个
std::string
初始化
1 | std::string str1 = "Hello"; |
1.5.3 std::string
的常用操作
- 获取字符串长度
使用 size()
或 length()
成员函数:
1 | std::string str = "Hello"; |
- 访问字符
使用 []
运算符或 at()
成员函数:
1 | std::string str = "Hello"; |
[]
不检查索引是否越界。at()
会检查索引,如果越界则抛出std::out_of_range
异常。
- 字符串连接
使用 +
运算符或 append()
成员函数:
1 | std::string str1 = "Hello"; |
- 比较字符串
使用 ==
、!=
、<
、>
等运算符:
1 | std::string str1 = "Hello"; |
- 查找子字符串
使用 find()
成员函数:
1 | std::string str = "Hello, World!"; |
- 提取子字符串
使用 substr()
成员函数:
1 | std::string str = "Hello, World!"; |
- 插入和删除
- 插入:使用
insert()
成员函数。 - 删除:使用
erase()
成员函数。
1 | std::string str = "Hello, !"; |
- 替换子字符串
使用 replace()
成员函数:
1 | std::string str = "Hello, World!"; |
- 转换为C风格字符串
使用 c_str()
或 data()
成员函数:
1 | std::string str = "Hello"; |
1.5.4 std::string
的迭代器
std::string
支持迭代器,可以用于遍历字符串中的字符。
示例:
1 | std::string str = "Hello"; |
std::string
的迭代器类似于指针,它可以指向字符串中的某个字符,并支持移动(如递增或递减)以访问其他字符。
1.5.5 std::string
的性能
- 动态内存管理:
std::string
会自动管理内存,但频繁的字符串操作(如拼接、插入、删除)可能会导致内存重新分配,影响性能。 - 小字符串优化:许多实现会对小字符串进行优化,避免频繁的内存分配。
std::string
是C++中处理字符串的强大工具,具有以下优点:
- 动态大小:无需手动管理内存。
- 丰富的功能:提供了大量的成员函数来操作字符串。
- 安全性:避免了C风格字符串的常见问题(如缓冲区溢出)。
- 易用性:支持运算符重载和迭代器,使用方便。
在C++中,可以通过重定向标准输出流(std::cout
)将输出内容写入文件,而不是显示在控制台上。以下是实现这一功能的简单方法:
1.5.6 标准数据流重定向
方法:使用 std::ofstream
和 std::cout.rdbuf()
1打开文件:使用 std::ofstream
创建一个文件输出流。
2保存 std::cout
的缓冲区:使用 std::cout.rdbuf()
获取 std::cout
的当前缓冲区。
3重定向 std::cout
:将 std::cout
的缓冲区设置为文件输出流的缓冲区。
4恢复 std::cout
:在完成文件写入后,将 std::cout
的缓冲区恢复为原来的缓冲区。
1 |
|
代码说明
打开文件:
- 使用
std::ofstream
创建文件输出流,并打开文件output.txt
。 - 如果文件打开失败,输出错误信息并退出程序。
- 使用
保存
std::cout
的缓冲区:`std::cout.rdbuf()` 获取 `std::cout` 的当前缓冲区,并保存到 `coutBuffer` 中。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3. **重定向 `std::cout`**:
- 使用 `std::cout.rdbuf(file.rdbuf())` 将 `std::cout` 的缓冲区设置为文件输出流的缓冲区。
4. **输出到文件**:
{0}. 使用 `std::cout` 输出的内容将被写入文件。
5. **恢复 `std::cout`**:
- 使用 `std::cout.rdbuf(coutBuffer)` 将 `std::cout` 的缓冲区恢复为原来的缓冲区。
6. **输出到控制台**:
- 恢复缓冲区后,`std::cout` 的输出将再次显示在控制台上。
7. **关闭文件**:
- 使用 `file.close()` 关闭文件。
- 文件 `output.txt` 的内容:This will be written to the file.
Hello, File!1
2
3
- 控制台的输出:This will be written to the console.
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
### `this` 指针
在C++中,**`this` 指针** 是一个隐含的指针,它指向当前对象的地址。`this` 指针在类的成员函数中自动可用,用于访问当前对象的成员变量和成员函数。它是C++实现面向对象编程的重要机制之一。
------
#### `this` 指针的特性
1. **隐含指针**:`this` 指针是编译器自动提供的,无需显式声明。
2. **指向当前对象**:`this` 指向调用成员函数的对象。
3. **常量指针**:`this` 是一个常量指针,其值不能被修改(即不能指向其他对象)。
4. **类型**:`this` 的类型是 `ClassName*`(指向当前类类型的指针)。在 `const` 成员函数中,`this` 的类型是 `const ClassName*`。
------
#### `this` 指针的用途
##### 1. 区分成员变量和局部变量
当成员变量与局部变量同名时,可以使用 `this` 指针明确指定访问的是成员变量。
```cpp
#include <iostream>
class MyClass {
private:
int value;
public:
void setValue(int value) {
this->value = value; // 使用 this 指针区分成员变量和参数
}
void printValue() {
std::cout << "Value: " << value << std::endl;
}
};
int main() {
MyClass obj;
obj.setValue(42);
obj.printValue(); // 输出:Value: 42
return 0;
}
—-在 setValue
函数中,this->value
明确表示访问的是成员变量 value
,而不是参数 value
。
this
指针的底层实现
this
指针实际上是成员函数的一个隐含参数。当调用成员函数时,编译器会自动将对象的地址作为第一个参数传递给成员函数。
例如,以下成员函数:
1 | void MyClass::setValue(int value) { |
在底层会被编译器转换为:
1 | void MyClass::setValue(MyClass* this, int value) { |
调用时:
1 | obj.setValue(42); |
实际上会被转换为:
1 | setValue(&obj, 42); |
注意:
用 ClassName*
定义一个变量,这个变量的功能和 this
并不完全一样,尽管它们都指向类的对象。以下是它们的区别和联系:
特性 | this 指针 |
ClassName* 变量 |
---|---|---|
生成方式 | 编译器自动生成 | 需要显式定义 |
作用域 | 仅在类的非静态成员函数中有效 | 可以在任何地方使用 |
指向对象 | 始终指向当前对象 | 可以指向任何同类型的对象 |
灵活性 | 不能修改指向的对象 | 可以修改指向的对象 |
用途 | 主要用于访问当前对象的成员 | 用于动态管理对象或传递对象指针 |
文件操作
在C++中,文件操作主要通过标准库中的<fstream>
头文件提供的类来实现。这些类包括:
ifstream
:用于从文件中读取数据(输入文件流)。ofstream
:用于向文件中写入数据(输出文件流)。fstream
:既可以读取也可以写入文件(输入输出文件流)。
以下是C++文件操作的详细介绍和示例:
1. 打开文件
文件操作的第一步是打开文件。可以使用open()
函数,或者直接在构造函数中指定文件名。
打开文件的模式
文件模式通过以下标志指定:
ios::in
:打开文件用于读取。ios::out
:打开文件用于写入。ios::app
:追加模式,写入数据时不会覆盖原有内容。ios::ate
:打开文件后定位到文件末尾。ios::trunc
:如果文件已存在,清空文件内容。ios::binary
:以二进制模式打开文件。
这些模式可以通过|
组合使用。
示例:打开文件
1 |
|
2. 写入文件
使用ofstream
或fstream
向文件中写入数据。
示例:写入文件
1 |
|
3. 读取文件
使用ifstream
或fstream
从文件中读取数据。
示例:读取文件
1 |
|
4. 文件位置操作
可以使用seekg()
和tellg()
(用于输入流)或seekp()
和tellp()
(用于输出流)来操作文件指针的位置。
示例:文件指针操作
1 |
|
5. 二进制文件操作
二进制文件操作使用ios::binary
模式,并通过read()
和write()
函数读写数据。
示例:二进制文件操作
1 |
|
6. 错误处理
文件操作中可能会发生错误,可以通过以下方式检查:
is_open()
:检查文件是否成功打开。fail()
:检查流是否处于错误状态。eof()
:检查是否到达文件末尾。
示例:错误处理
1 | ifstream inFile("example.txt"); |
总结
C++中的文件操作主要通过<fstream>
实现,支持文本和二进制文件的读写。关键点包括:
- 使用
ifstream
、ofstream
和fstream
类。 - 通过
open()
或构造函数打开文件。 - 使用
<<
和>>
进行文本读写,使用read()
和write()
进行二进制读写。 - 通过
seekg()
、tellg()
等操作文件指针。 - 注意错误处理和文件关闭。
c++中的类型转换
在C++中,类型转换是将一种数据类型转换为另一种数据类型的过程。C++提供了四种类型转换运算符,分别是:static_cast
、dynamic_cast
、const_cast
和 reinterpret_cast
。这些运算符提供了更安全和明确的类型转换方式,相比于C语言中的强制类型转换,C++的类型转换运算符更加精细和可控。
1. static_cast
static_cast
是最常用的类型转换运算符,用于执行非多态类型的转换。它通常用于基本数据类型之间的转换,以及具有继承关系的类指针或引用之间的转换。
使用场景:
- 基本数据类型之间的转换,如
int
转double
。 - 将指针或引用从派生类转换为基类(上行转换)。
- 将指针或引用从基类转换为派生类(下行转换,但不进行运行时类型检查)。
- 将
void*
指针转换为其他类型的指针。
示例:1
2
3
4
5
6
7
8int i = 10;
double d = static_cast<double>(i); // 将 int 转换为 double
class Base {};
class Derived : public Base {};
Base* b = new Derived;
Derived* d = static_cast<Derived*>(b); // 将 Base* 转换为 Derived*
2. dynamic_cast
dynamic_cast
主要用于处理多态类型的转换,即在继承体系中进行向下转换(从基类指针或引用转换为派生类指针或引用)。它在运行时进行类型检查,如果转换不合法,则返回 nullptr
(对于指针)或抛出 std::bad_cast
异常(对于引用)。
使用场景:
- 在继承体系中进行向下转换。
- 用于多态类型(即基类必须有虚函数)。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Base {
public:
virtual void foo() {}
};
class Derived : public Base {};
Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b); // 将 Base* 转换为 Derived*
if (d) {
// 转换成功
} else {
// 转换失败
}
3. const_cast
const_cast
用于修改类型的 const
或 volatile
属性。它可以将 const
对象转换为非 const
对象,或者将 volatile
对象转换为非 volatile
对象。
使用场景:
- 去除
const
或volatile
属性。 - 不能用于修改对象的实际类型。
示例:1
2
3const int i = 10;
int* p = const_cast<int*>(&i); // 去除 const 属性
*p = 20; // 修改值,但这是未定义行为,因为 i 本身是 const
4. reinterpret_cast
reinterpret_cast
是最危险的类型转换运算符,它提供了低级别的重新解释比特模式的转换。它通常用于不相关的类型之间的转换,如将指针转换为整数,或将一种类型的指针转换为另一种类型的指针。
使用场景:
- 指针和整数之间的转换。
- 不相关类型指针之间的转换。
- 函数指针之间的转换。
示例:1
2
3
4
5int i = 10;
int* p = &i;
long addr = reinterpret_cast<long>(p); // 将指针转换为整数
char* c = reinterpret_cast<char*>(p); // 将 int* 转换为 char*
对比表格
| 转换类型 | 检查时机 | 安全性 | 典型用途 |
|—————————|—————|————|———————————————|
| static_cast | 编译时 | 高 | 显式类型转换、继承体系转换 |
| dynamic_cast | 运行时 | 中 | 多态类型安全向下转型 |
| const_cast | 编译时 | 低 | 修改const/volatile属性 |
| reinterpret_cast| 编译时 | 危险 | 低层二进制数据重新解释 |
转换选择建议
- 优先使用static_cast
多态类型转换用dynamic_cast
除非必要,避免使用const_cast和reinterpret_cast
完全禁用C风格强制转换:
1 | // 避免使用* |
练习
以下是基于图中主题的40道题目,涵盖选择题、填空题、问答题和改错题。答案统一放在文末。
选择题
- C++中函数的缺省参数的作用是什么?
A. 提高代码执行效率
B. 简化函数调用
C. 增加函数的功能
D. 减少代码行数 - 以下哪个是C++中函数重载的正确示例?
A.void func(int a); int func(int a, int b);
B.void func(int a); int func(int a);
C.void func(int a); void func(double a);
D.void func(int a); void func(int a, int b = 10);
C++中名字空间的作用是什么?
A. 提高代码执行效率
B. 避免命名冲突
C. 增加代码的可读性
D. 减少内存使用C++中用于标准输出的流对象是?
A.std::cin
B.std::cout
C.std::cerr
D.std::clog
std::string
类的哪个成员函数用于获取字符串的长度?
A.length()
B.size()
C.capacity()
D.max_size()
this
指针在C++中的作用是什么?
A. 指向当前对象的地址
B. 指向基类的地址
C. 指向静态成员的地址
D. 指向全局变量的地址C++中用于动态内存分配的关键字是?
A.malloc
B.new
C.alloc
D.create
以下哪个是C++中最合适的缺省参数声明?
A.void func(int a = 10, int b);
B.void func(int a, int b = 10);
C.void func(int a = 10, int b = 20, int c);
D.void func(int a, int b, int c = 30);
- C++中用于标准错误输出的流对象是?
A.std::cin
B.std::cout
C.std::cerr
D.std::clog
std::string
类的哪个成员函数用于查找子字符串?
A.find()
B.search()
C.locate()
D.index()
填空题
- 在C++中,函数的缺省参数必须从__开始依次指定。
- C++中函数重载的条件是函数的__必须不同。
- 使用__关键字可以定义一个名字空间。
- C++中用于标准输入的流对象是__。
std::string
类的__成员函数用于提取子字符串。this
指针的类型是__。- 在C++中,使用__关键字可以动态分配内存。
- 名字空间的作用是避免__。
std::string
类的__成员函数用于返回C风格字符串。- 在C++中,
std::cin
的__成员函数用于清除错误状态。
问答题
- 解释C++中函数的缺省参数的作用,并给出一个示例。
- 什么是函数重载?在C++中如何实现函数重载?
- 名字空间在C++中的作用是什么?如何定义和使用名字空间?
- 解释C++中标准输入输出流的作用,并列举常用的流对象。
std::string
类的主要功能是什么?列举常用的成员函数。- 解释
this
指针的作用,并给出一个使用this
指针的示例。 - 在C++中,如何使用
new
和delete
进行动态内存管理? - 什么是迭代器?如何在
std::string
中使用迭代器? - 解释C++中
const
成员函数的作用,并给出一个示例。 - 如何在C++中重定向标准输出流到文件?
改错题
以下代码有错误,请指出并修正:
1
void func(int a = 10, int b);
以下代码有错误,请指出并修正:
1
2void func(int a);
void func(int a,int b=10);以下代码有错误,请指出并修正:
1
2
3
4
5
6
7namespace MyNamespace {
int value = 10;
}
int main() {
std::cout << value << std::endl;
return 0;
}以下代码有错误,请指出并修正:
1
2
3
4
5
6
7
8class MyClass {
public:
void print() const {
this->value = 10;
}
private:
int value;
};以下代码有错误,请指出并修正:
1
2
3int* ptr = new int;
delete ptr;
delete ptr;以下代码有错误,请指出并修正:
1
2
3
4
5
6
7
8class MyClass {
public:
MyClass(int a) {}
};
int main() {
MyClass obj;
return 0;
}以下代码有错误,请指出并修正:
1
2
3
4
5
6class MyClass {
public:
void func() {
return this;
}
};
答案
- B
C
B
B
A
A
- B
B //要求选择最合适的,D可能存在二意性问题。
C
A
右
参数列表
namespace
std::cin
substr()
ClassName*
new
- 命名冲突
c_str()
clear()
缺省参数允许在调用函数时省略某些参数,编译器会自动使用默认值。示例:
void func(int a = 10);
- 函数重载允许在同一作用域内定义多个同名函数,只要它们的参数列表不同。
- 名字空间用于组织代码,避免命名冲突。定义:
namespace MyNamespace {}
,使用:MyNamespace::value
。 - 标准输入输出流用于处理输入输出操作。常用流对象:
std::cin
、std::cout
、std::cerr
、std::clog
。 std::string
类用于表示和操作字符串。常用成员函数:length()
、substr()
、find()
、append()
。this
指针指向当前对象的地址。示例:void setValue(int value) { this->value = value; }
- 使用
new
分配内存,delete
释放内存。示例:int* ptr = new int; delete ptr;
- 迭代器用于遍历容器中的元素。示例:
for (auto it = str.begin(); it != str.end(); ++it)
const
成员函数保证MyClass* func() { return this; }
不修改对象的状态。示例:void print() const { std::cout << value; }
- 使用
std::ofstream
和std::cout.rdbuf()
重定向输出流到文件。 - 修正:
void func(int a, int b = 10);
- 修正:二义性问题。
- 修正:
std::cout << MyNamespace::value << std::endl;
- 修正:
void print() const { std::cout << value; }
- 修正:
delete ptr;
(只删除一次) - 修正:
MyClass obj(10);
- 修正:
MyClass* func() { return this; }