
在C++中,类类型转换是指将一个类的对象转换为另一个类的对象,或者将一个类的对象转换为基本数据类型等。C++提供了多种类型的转换机制,包括隐式类型转换和显式类型转换。以下是关于C++类类型转换的详细介绍:
构造函数实现的隐式转换
class B {
public:
B(int x) { /* ... */ }
};这时,可以将int类型的值隐式转换为B类型的对象:
B b = 5; // 通过B的构造函数将5隐式转换为B对象在类类型有多个参数时,可以使用{ xxx ,xxx },的形式来进行转换,不能使用(),因为()会计算出括号内最后一个表达式的值
类型转换运算符实现的隐式转换
class A {
public:
operator int() const { return 10; }
};这时,A类型的对象可以隐式转换为int类型:
A a;
int x = a; // 通过A的类型转换运算符将a隐式转换为int这种隐式转换可能会导致一些意外的错误,因此可以通过在构造函数前加上explicit关键字来禁止这种隐式转换:
class B {
public:
explicit B(int x) { /* ... */ }
};这样,B b = 5;就会报错,而必须显式地调用构造函数:B b(5);。
类类型的对象之间也可以隐式转换,需要相应的构造函数⽀持
在C++中,static成员是类的一个重要特性,它与类本身相关联,而不是与类的某个具体对象相关联。这意味着static成员在类的所有对象之间是共享的。以下是对static成员的详细介绍:
static成员变量定义与初始化
static成员变量是类的所有对象共享的变量。它在类的定义中声明,但需要在类的定义外进行初始化。 ⽤static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进⾏初始化。例如:class MyClass {
public:
static int count; // 声明static成员变量
};
int MyClass::count = 0; // 初始化static成员变量static成员变量的初始化必须在类的定义外进行,且只能初始化一次。访问方式
static成员变量可以通过类名或类的对象来访问,但推荐使用类名访问,以体现其与类的关系。例如:MyClass::count = 10; // 通过类名访问
MyClass obj;
obj.count = 20; // 通过对象访问(不推荐,但合法)static成员变量都是同一个变量。生命周期
static成员变量的生命周期从程序开始运行时初始化,到程序结束时销毁。它不依赖于类的对象的生命周期。static成员函数定义与调用
static成员函数是与类相关联的函数,而不是与类的某个具体对象相关联。它不能访问非static成员变量和非static成员函数,因为这些成员需要对象的上下文。例如:class MyClass {
public:
static void print() {
std::cout << "Static function" << std::endl;
}
};static成员函数可以通过类名或类的对象来调用,但推荐使用类名调用。例如:MyClass::print(); // 通过类名调用
MyClass obj;
obj.print(); // 通过对象调用(不推荐,但合法)特点
static成员函数没有this指针,因为它不依赖于具体的对象。static成员变量和其他static成员函数。应用场景
class MyClass {
public:
static void incrementCount() { count++; }
static int getCount() { return count; }
private:
static int count;
};
int MyClass::count = 0;
int main() {
MyClass::incrementCount();
std::cout << MyClass::getCount() << std::endl; // 输出1
return 0;
}static成员的存储位置static成员变量和static成员函数的存储位置通常在程序的全局数据区。它们在程序启动时分配内存,在程序结束时释放内存。static成员变量在全局数据区中有一个固定的地址,所有对象共享这个地址。static成员变量和static成员函数是类的静态特性,它们与类本身相关联,而不是与类的对象相关联。static成员变量需要在类的定义外初始化,并且可以通过类名或对象访问。⽤static修饰的成员函数,称之为静态成员函数 static成员函数没有this指针,只能访问类的static成员变量和其他static成员函数。在C++中,友元(Friend) 是一个非常重要的概念,它允许某些特定的函数或类访问另一个类的私有(private)和保护(protected)成员。这在某些情况下非常有用,尤其是当你需要在类的封装性与功能需求之间找到平衡时。
friend关键字声明。this指针。定义
friend关键字声明。例如:class MyClass {
private:
int privateData;
public:
MyClass(int data) : privateData(data) {}
friend class FriendClass; // 声明友元类
};
class FriendClass {
public:
void printPrivateData(const MyClass& obj) {
std::cout << "Private Data: " << obj.privateData << std::endl;
}
};FriendClass是MyClass的友元类,因此FriendClass的所有成员函数都可以访问MyClass的私有成员privateData。特点
friend关键字声明,并指定所属类和函数名。• 如果⼀个类定义在另⼀个类的内部,这个内部类就叫做内部类。内部类是⼀个独⽴的类,跟定义在全局相⽐,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
• 内部类默认是外部类的友元类。
• 内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地⽅都⽤不了。
内部类和外部类为平行关系,计算大小时不算内部类,内部类不算外部类的一部分,收访问限定符的限制
通常情况下,我们定义的是有名对象。在C++中,匿名对象是指没有显式命名的对象。它们通常在需要临时使用某个类的对象时被创建,使用完毕后立即销毁。匿名对象⽣命周期只在当前⼀⾏,⼀般临时定义⼀个对象当前⽤⼀下即可。
当使用动态内存分配(new)创建数组时,构造函数的调用机制与静态数组是相同的,但有一些额外的注意事项。
动态数组的构造函数调用
Sum* arr = new Sum[n]; // 动态创建长度为n的Sum数组这行代码会: