C++重学 函数重载,extern C,构造拷贝,explicit,new delete

本文详细探讨了C++中的关键概念,包括函数重载的实现原理,如何在C++中使用`extern C`调用C语言方法,C++与C封装的区别,构造函数与拷贝构造函数的使用细节,明确使用`explicit`关键字的作用,以及`new`和`delete`操作符在动态对象创建和内存管理中的应用。此外,还讨论了深拷贝与浅拷贝的概念,并强调了正确使用`new`避免内存错误的重要性。

函数重载

函数参数个数,类型,顺序不同
实现原理
编译器会修改函数名,带上参数类型

extern C

在C++中想调用C语言方法

// Cpp
#include <iostream>
// 在C++中想调用C语言方法
extern "C" {
	#include "test.h"
}

int main()
{
	show(); // 在C++中函数可以重载,编译器会把函数名偷偷修改了

    std::cout << "Hello World!\n";
}

// .c
#include "test.h"

void show() {
	printf("sfs");
}

// .h
#pragma once
#include<stdio.h>

void show();
// .h
#pragma once
// 如果这是一段cpp的代码,那么加入extern "C"{和}处理其中的代码。
#ifdef __cplusplus 
extern "C" {
#endif

#include<stdio.h>

	void show();

#ifdef __cplusplus
}
#endif // !__cplusplus

C++与C封装的区别

C 中封装,属性与行为分开处理了,且类型转换检测不够
struct class 默认权限不同

构造,拷贝

  1. 当我们自己写了拷贝构造,系统不会在提供其他构造
  2. 当我们自己写了有参构造,系统不会提供默认构造,但是会提供默认拷贝
	// 普通构造
	Person(int age) : age(age) {

	}

	Person p1(100);
	Person p1 = Person(100);
	Person(10); // 匿名对象

	// 拷贝构造
	// 拷贝构造调用时机
	// 用以创建的对象构造新对象
	// 以值传递的方式给函数参数传值,调用拷贝
	// 以值方式返回局部遍历,调用拷贝
	// release 模式下会优化
	Person(const Person& p) {

	}

	 Person p1(p2);
	 Person p1 = p2;
Person p; // 调用默认构造函数
Person p1(); // 编译器认为是函数声明

// 显示法调用
Person p4 = Person(100); // 调用有参
Person P5 = Person(p4); // 调用拷贝构造

// 匿名对象,这段代码结束后就释放对象
Person p6;

// 错误,编译器认为是 Person p5;(声明) p5被重定义,拷贝构造必须做右值
// Person(p5);

深拷贝,浅拷贝
浅拷贝
拷贝构造函数是系统默认拷贝,简单的值拷贝(拷贝了地址而已)
name会因为释放2次而出错

	int age;
	char* name;
	Person(int age, char *_name) : age(age) {
		std::cout << "putong" << std::endl;
		name = (char*)malloc(strlen(_name) + 1);
		strcpy(name, _name);
	}

深拷贝,(重写拷贝构造)
自行给指针分配空间,

	// 拷贝构造
	Person(const Person& p) {
		std::cout << "kaobei" << std::endl;
		age = p.age;
		name = (char*)malloc(strlen(p.name) + 1);
		strcpy(name, p.name);
	}

在这里插入图片描述

类对象作为类的成员
构造顺序:先将类对象以此狗仔

class Phone {
	string name;
public:
	Phone(string name): name(name) {};
	~Phone() {};
};

class Game {
public:
	Game() {};
	~Game() {};
};
class Person
{
	int age;
	char* name;
	string address;
	Phone p;
	Game game;
	
public :
	// 必须要有Phone(string name): name(name) {};构造才行
	Person(string phoneName) : p(phoneName) {

	}
}

explicit

防止隐式类型转换


#pragma once
class MyString
{
public:
	MyString(const char* str) {

	}
	
	MyString(int a) {

	}

	// explicit MyString(int a) {
	//
	// }

	char* str;
};


void test01() {
	// MyString(const char* str)有参构造
	MyString str = "abs";
	
	// MyString(int a) 有参构造
	MyString str2(10);
	
	// 隐式类型转换
	// MyString str3 = MyString(100);
	// explicit加上后,这句报错了。
	// explicit:防止隐式类型转换
	MyString str3 = 100;
	
}

new 动态对象创建

malloc

  1. 必须确认对象长度
malloc(strlen(strings) + 1)malloc(sizeOf(Person));
  1. malloc返回void * 指针,所以必须强转后才能使用。
Person *p =(Person *)malloc(sizeOf(Person));
  1. malloc分配内存可能会失败。所以必须判断返回值确认是否分配成功
if(p == NULL) {
	return 0;
}
  1. 使用对象前必须进行初始化

new delete
运算符
在堆区开辟空间,所有new出来的对象,都会返回该类型的指针

Person *person = new Person;
delete person;

Person *persons = new Person[10]; // 一定调用默认构造
delete[] persons;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值