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;
}