在C++中,构造函数成员初始化列表是一种在构造函数体执行之前初始化类成员变量的机制。这不仅能提高效率,还是初始化具有非默认构造函数的类成员、常量成员、引用成员和没有默认构造函数的基类的唯一方法。

构造函数成员初始化列表位于构造函数参数列表之后,函数体之前,以冒号开始,后面跟着一个或多个用逗号分隔的初始化器。每个初始化器都有一个成员变量名字和相应的初始化表达式,这个表达式可以是任意复杂度的。

下面是构造函数成员初始化列表的一个示例:

1
2
3
4
5
6
7
8
9
10
11
class MyClass {
public:
MyClass(int x, double y) : id(x), value(y) {
// 构造函数体
}

private:
const int id; // 常量成员,必须在成员初始化列表中初始化
double value; // 普通成员,可以在成员初始化列表中初始化
};

阅读全文 »

在C++中,对值的分类非常重要,因为它决定了你可以对这些值做什么操作。左值(lvalue)和右值(rvalue)是C++中的两种主要的表达式类别,而左值引用和右值引用则是与之对应的引用类型。

左值 (Lvalue)

左值是指那些表达式,它们指向内存中的一个固定位置,这样的表达式可以出现在赋值语句的左侧。它们通常是一个变量、数组的一个元素或者一个对象的一个属性。左值可以取地址,即可以使用&运算符来得到其内存地址。

示例:

1
2
int x = 10; // x是一个左值
x = 20; // x可以在赋值语句的左侧出现

在这个例子中,x是一个左值,因为你可以对它赋值。x具有一个持久的内存地址,可以在程序的多个地方引用和修改。

阅读全文 »

Java基本数据类型

类型类别 类型名称 大小(位) 取值范围 默认值
整数类型 byte 8 -128 到 127 0
short 16 -32,768 到 32,767 0
int 32 -2^31 到 2^31-1 0
long 64 -2^63 到 2^63-1 0L
浮点数类型 float 32 精度约为 6-7 位十进制数 0.0f
double 64 精度约为 15 位十进制数 0.0d
字符类型 char 16 0 到 65,535(无符号)
布尔类型 boolean 未指定 truefalse false

注意:

  1. Java的char类型是基于Unicode编码的,因此可以表示全球上几乎所有的字符。
  2. Java的基本数据类型大小是固定的,与平台无关,这有助于Java程序具有良好的可移植性。
  3. Java中没有表示无符号整数的基本数据类型,在需要大范围无符号数据时通常使用更大的类型或使用类库。
  4. 布尔类型boolean并没有明确指定大小,但仅能取truefalse中的一个值。
阅读全文 »

C++的模板(Templates)和Java的泛型(Generics)都是用于实现代码的参数化类型,但是它们在设计理念、实现机制和功能上有很大的不同。下面是几个主要的区别:

1. 编译时机

  • C++模板是在编译时进行实例化的。当模板用特定类型实例化时,编译器会生成这个类型的具体代码。这种方法称为模板元编程(template metaprogramming),它允许非常灵活和强大的类型操作,但也会增加编译时间和生成的二进制文件大小。
  • Java泛型是基于类型擦除实现的,这意味着泛型信息只在编译时用于类型检查,然后被擦除,运行时并不存在具体类型的信息。泛型类和方法在编译后都会转换为普通的类和方法,泛型类型参数会替换为它们的边界或者Object。因此,在运行时是没有类型参数的具体信息的。
阅读全文 »

在C++中,const关键字的位置相对于类型和星号(*,用于指针)或者引用符号(&)会影响它修饰的内容。这些不同的位置可以表示不同的含义,例如指针常量、常量指针、常量引用等。以下是const位置对含义的影响:

1. 指针和const

  • const在类型前:

    1
    const int* ptr;

    这意味着ptr是一个指向const int的指针。你不能通过这个指针修改它指向的值,但是你可以修改指针ptr本身,使它指向另一个地址。

  • const在星号后:

    1
    int* const ptr = &someIntVar;

    这意味着ptr是一个指向int的常量指针。你可以修改指针所指向的值,但是不能修改指针ptr本身的值,即不能让它指向另一个地址。这里,指针必须在声明时初始化,并且之后不能再指向其他地址。

  • const同时在类型前和星号后:

    1
    const int* const ptr = &someIntVar;

    ptr是一个指向const int的常量指针。既不能通过指针修改所指向的值,也不能修改指针本身的值。

阅读全文 »

虚函数-纯虚函数区别

1
2
3
1. 虚函数允许派生类根据自己的需要重写基类的行为。在基类中,你通过在函数声明前加上virtual关键字来声明虚函数。
2. 纯虚函数(Pure Virtual Function)
纯虚函数是一种特殊的虚函数,你无法为其提供实现,而是在其声明时将其初始化为0。声明一个或多个纯虚函数的类称为抽象类(Abstract Class),你不能创建抽象类的实例。纯虚函数的目的是强制派生类提供自己的实现。

在C++中,成员函数的重写(override)是多态的一个核心概念,它允许派生类改变基类中某个函数的行为。对于虚函数来说,派生类确实可以直接重写基类中的虚函数。但是,对于非虚函数,派生类也可以提供自己的实现,这通常被称为隐藏(hiding)而不是重写。

我们来区分一下:

  1. 函数隐藏(Function Hiding):如果派生类声明了一个和基类同名的成员函数(即使参数列表不同),它将隐藏所有基类中具有相同名称的成员函数。在派生类的对象中调用这个函数时,只有派生类的版本可见,基类的版本被隐藏了。
  2. 函数重写(Function Overriding):仅当派生类中的函数与基类中的虚函数有相同的签名(函数名、参数列表、const属性等)时,才称之为重写。在派生类的对象上调用这样的函数时,将使用动态绑定,根据对象的实际类型调用相应类的函数实现。
阅读全文 »

在Java和C++中,包含和访问库中的类型(如字符串)有不同的机制。

Java中的import语句:

在Java中,当你使用import语句时,它告诉编译器在编译时需要查找哪些类。Java中的String类位于java.lang包中,该包是自动被所有Java程序导入的,因此你通常不需要显式导入java.lang.String。你可以直接使用String类而不需要任何前缀。

1
2
3
4
5
6
7
8
import java.util.List; // 导入java.util包中的List接口

public class MyClass {
public static void main(String[] args) {
String myString = "Hello, World!"; // 直接使用String
List<String> myList; // 使用导入的List接口
}
}

C++中的#include指令:

在C++中,当你使用#include <string>预处理指令时,你是在告诉编译器在编译之前将<string>头文件的内容文本替换到源文件中。然而,C++标准库中的很多功能都是在命名空间std中定义的。

因此,当你包含<string>头文件后,你还需要使用std::的前缀来访问std命名空间中的string类。

阅读全文 »

在C++中,struct(结构体)和class(类)的基本用法非常相似,因为C++中的结构体可以含有函数和构造函数,它们都可以用来定义包含数据成员和成员函数的自定义类型。不过,结构体和类之间存在一些关键区别:

默认访问权限

  • struct:默认的成员访问权限和继承访问权限是public
  • class:默认的成员访问权限和继承访问权限是private

这意味着当你使用structclass关键字定义类型时,不显式指定访问修饰符的成员在struct中默认是公开的,在class中默认是私有的。

阅读全文 »

在C++中,using关键字有几种用途,包括定义类型别名、引入命名空间中的名称,以及在C++11及后续版本中用于模板别名。以下是using关键字的几种常见用途:

1. 类型别名

typedef一样,using可以用来给类型定义一个新的名称。这在C++11中引入,目的是为了提供一种比typedef更直观的语法来定义类型别名。

用法:

1
using new_type_name = existing_type;

示例:

1
2
3
4
5
6
7
using Integer = int;
using StringList = std::list<std::string>;
using CharArray = char[10];

Integer num = 42;
StringList names;
CharArray array = {'H', 'e', 'l', 'l', 'o'};
阅读全文 »

typedef是C和C++中的一个关键字,它用于给数据类型创建一个新的名称(别名)。通过typedef,你可以为复杂的数据类型定义一个易于记忆和使用的名称。这在处理结构体、联合体、函数指针等复杂类型时特别有用。

基本用法

1
typedef existing_type new_type_name;

示例

1. 为基本数据类型定义别名

1
2
3
4
5
typedef unsigned long ulong;
typedef double real;

ulong number = 123456789;
real pi = 3.14159;
阅读全文 »
0%