C++——类的真正形态、构造函数的调用

1.class和struct的区别:用struct定义类时,所有成员的默认访问级别为public;用class定义类时,所有成员的默认访问级别为private

2.类定义中成员变量i和j的初始值

复制代码
#include <stdio.h>
class Test {
private:
	int i;
	int j;
public:
	int getI() {
		return i;
	}
	int getJ() {
		return j;
	}
};
Test gt;
int main() {
	printf("gt.i=%d\n", gt.getI());
	printf("gt.j=%d\n", gt.getJ());
	Test t1;
	printf("t1.i=%d\n", t1.getI());
	printf("t1.j=%d\n", t1.getJ());
	Test* pt = new Test;
	printf("pt.i=%d\n", pt->getI());
	printf("pt.j=%d\n", pt->getJ());
    delete pt;
	return 0;
}

结果:

gt存放在全局区,静态存储区创建的成员,成员变量初始值为0;t1在栈区,初始值为随机值;pt在堆空间,初始值是随机值

2.构造函数的自动调用

复制代码
#include <stdio.h>
class Test {
public:
	Test(){
		printf("Test()\n");
	}
	Test(int v){
		printf("Test(int v)\n");
	}
};
int main() {
	Test t; //Test()
    //初始化方式:
	Test t1(1); //Test(int v)
	Test t2 = 1; //Test(int v)
    Test t3=Test(100); //Test(int v)
	return 0;
}

一些特殊情况下需要手工调用构造函数

定义一个数组,如果默认调用时,均调用无参构造函数

复制代码
#include <stdio.h>
class Test {
private:
	int m_value;
public:
	Test(){
		printf("Test()\n");
		m_value = 0;
	}
	Test(int v){
		printf("Test(int v)\n");
		m_value = v;
	}
	int getValue() {
		return m_value;
	}
};
int main() {
	Test ta[3];
	for (int i = 0; i < 3; i++) {
		printf("ta[%d].getValue()=%d\n", i, ta[i].getValue());
	}
	return 0;
}

结果:

手动调用后:

复制代码
#include <stdio.h>
class Test {
private:
	int m_value;
public:
	Test(){
		printf("Test()\n");
		m_value = 0;
	}
	Test(int v){
		printf("Test(int v)\n");
		m_value = v;
	}
	int getValue() {
		return m_value;
	}
};
int main() {
	Test ta[3] = {Test(),Test(1),Test(2)};
	for (int i = 0; i < 3; i++) {
		printf("ta[%d].getValue()=%d\n", i, ta[i].getValue());
	}
	return 0;
}

结果:

3.示例:开发一个数组类解决原生数组的安全性问题:提供函数获取数组长度、获取数组元素、设置数组元素

intArray.h

复制代码
#pragma once
class IntArray {
private:
	int m_length;
	int* m_pointer;

public:
	IntArray(int len);
	IntArray(const IntArray& obj);
	int length();
	bool get(int index, int& value); //index是数组下标
	bool set(int index, int value);
	void free();
};

intArray.cpp

复制代码
#include "intArray.h"
IntArray::IntArray(int len) {
	m_pointer = new int[len];
	for (int i = 0; i < len; i++) {
		m_pointer[i] = 0;
	}
	m_length = len;
}
IntArray::IntArray(const IntArray& obj) {
	m_length = obj.m_length;
	m_pointer = new int[obj.m_length];
	for (int i = 0; i < obj.m_length; i++) {
		m_pointer[i] = obj.m_pointer[i];
	}
}
int IntArray::length() {
	return m_length;
}
bool IntArray::get(int index, int& value) {
	bool ret = (0 <= index) && (index < length());
	if (ret) {
		value = m_pointer[index];
	}
	return ret;
}
bool IntArray::set(int index, int value) {
	bool ret = (0 <= index) && (index < length());
	if (ret) {
		m_pointer[index] = value;
	}
	return ret;
}
void IntArray::free() {
	delete[]m_pointer;
}

main.cpp

复制代码
#include <stdio.h>
#include "intArray.h"
int main() {
	
	IntArray a(5); //调用 IntArray 的构造函数
	for (int i = 0; i < a.length(); i++) {
		a.set(i, i + 1);
	}
	for (int i = 0; i < a.length(); i++) {
		int value = 0;
		if (a.get(i, value)) {
			printf("a[%d]=%d\n", i, value);
		}
	}
    IntArray b=a;
    for (int i = 0; i < b.length(); i++) {
		int value = 0;
		if (b.get(i, value)) {
			printf("b[%d]=%d\n", i, value);
		}
	}
	a.free();
    b.free();
    return 0;
}

4.两个特殊的构造函数------无参构造函数、拷贝构造函数

无参构造:当类中没有定义构造函数时,编译器就默认提供一个无参构造函数,并且函数体为空

拷贝构造:当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单进行成员变量的值复制

若定义带参构造函数后,编译器不会自动生成 默认无参构造函数,若自定义拷贝构造函数后,编译器不会自动生成默认无参构造函数,若只定义了带参构造函数时,编译器仍然会自动生成默认的拷贝构造函数

5.深拷贝与浅拷贝

复制代码
#include <stdio.h>
class Test {
private:
	int i;
	int j;
	int* p;
public:
	int getI() {
		return i;
	}
	int getJ() {
		return j;
	}
	int* getP() {
		return p;
	}
	Test(const Test& t) {
		i = t.i;
		j = t.j;
	}
	Test(int v) {
		i = 1;
		j = 2;
		p = new int;
		*p = v;
	}
	void free() {
		delete p;
	}
};

int main() {
	Test t1(3);
	Test t2 = t1;
	printf("t1.i=%d,t1.j=%d,t1.p=%p\n", t1.getI(), t1.getJ(), t1.getP());
	printf("t2.i=%d,t2.j=%d,t2.p=%p\n", t2.getI(), t2.getJ(), t2.getP());
	t1.free();
	t2.free(); //报错,因为t1和t2的指针指向同一块内存空间,t1释放之后,t2就不能再释放了
	return 0;
}

为了防止这种错误,t2应该也要指向一个新的堆空间,即深拷贝

复制代码
#include <stdio.h>
class Test {
private:
	int i;
	int j;
	int* p;
public:
	int getI() {
		return i;
	}
	int getJ() {
		return j;
	}
	int* getP() {
		return p;
	}
	Test(const Test& t) {
		i = t.i;
		j = t.j;
		p = new int;
		*p = *t.p;
	}
	Test(int v) {
		i = 1;
		j = 2;
		p = new int;
		*p = v;
	}
	void free() {
		delete p;
	}
};

int main() {
	Test t1(3);
	Test t2(t1);
    //或者也可以写成Test t2=t1
	printf("t1.i=%d,t1.j=%d,t1.p=%p\n", t1.getI(), t1.getJ(), t1.getP());
	printf("t2.i=%d,t2.j=%d,t2.p=%p\n", t2.getI(), t2.getJ(), t2.getP());
	t1.free();
	t2.free(); //报错,因为t1和t2的指针指向同一块内存空间,t1释放之后,t2就不能再释放了
	return 0;
}
相关推荐
2601_9620715710 小时前
【Java报错已解决】org.springframework.beans.factory.BeanCreationException
java·开发语言
淡海水11 小时前
07-04-并发-ConcurrentBag-T-工作窃取WorkStealing算法
开发语言·算法·c#·bag·concurrent·workstealing
CS_Zero12 小时前
C语言sizeof是函数吗?
c语言·开发语言
-今昭-13 小时前
《V2V 迁移实战:将 VMware 虚拟机转为 OpenStack 可用 Glance qcow2 镜像》
开发语言·python
黑马程序员毕设14 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
_Twink1e15 小时前
openJiuwen 实训营 Day 1 · WorkSwarm 入门教程
开发语言·c++·openjiuwen
问天_观心15 小时前
大模型微调学习(一)
开发语言·人工智能·学习·语言模型·github
阿里嘎多学长15 小时前
2026-09-03 GitHub 热点项目精选
开发语言·程序员·github·代码托管
dong_junshuai16 小时前
每天一个开源项目#87 fmt:24.5K Stars 的 C++ 格式化核心
c++·开源·github
源代码•宸16 小时前
前置准备:定时微服务背景和现状
开发语言·经验分享·后端·微服务·云原生·架构·golang