这篇小教程,推荐用电脑看,打开你们的ide,直接复制粘贴代码
类与结构体的不同(P47)
C++较比之前的我们学习的C语言增加了一个class(类)类型,即我们现在所要学习的类,那么他与struct(结构体)有什么不同呢?
* 首先让我们想一下,结构体里面可以有成员函数嘛?可以有public/private/protected标识符嘛?
是的, 在c++里,结构体里是可以有成员函数和访问限定符的(但是c语言是不支持的),这里为了让c++更好的向下兼容c,即c语言的代码,可以跑在c++里面(一般同学们用的时候cpp文件吧?就算是编写c语言的时候)。
* 接着,我们要明确一个概念,struct里的成员,不设置限定符的时候,默认是public,这就是我们在写c语言的时候,直接可以访问结构体里成员的原因;但是在class里的成员,默认是private的,这是二者的不同之处。
* 当然了,什么时候是使用结构体呢?严格来说,学习了c++语言后,我们应该杜绝结构体了,但是如果非要这么问,那么我们要这么回答,如果希望成员是公共的(public),那么我们就用结构体,如果希望是私有的,那么就用class。
* 在这里说一下,如果希望完整的学习类,那么就要学习类的构造,默认构造,构造列表,析构,继承等等一系列类的特性,而且在c++中,可以把struct看作是一个特殊的class来进行处理。
* 现在给出一个简单的类声明的示例
#include <iostream>
using namespace std;
class Node {
public: // 公有
int a;
Node() { // 默认构造
a = 1;
b = 2;
c = 3;
}
Node(int a, int b, int c) { // 有参构造函数
this->a = a;
this->b = b;
this->c = c;
}
void displayAll() { // 成员函数
displayA();
displayB();
displayC();
}
void displayA() {
cout << a << endl;
}
private: // 私有
int b;
void displayB() {
cout << b << endl;
}
protected: // 保护
int c;
void displayC() {
cout << c << endl;
}
};
class Node2 : public Node { // 公有继承
};
class Node3 : private Node { // 私有继承
};
class Node4 : protected Node { // 保护继承
};
int main() {
Node n;
n.displayAll();
n.displayA();
Node2 m2;
m2.displayAll();
//Node3 m3;
//m3.displayAll(); 无法访问
//Node4 m4;
//m4.displayAll(); 无法访问
//n.displayB(); 无法调用
//n.displayC(); 无法调用
return 0;
}
在类外定义成员函数(P48)
这个就很简单啦,直接上代码
#include <iostream>
using namespace std;
class Node {
public: // 公有
int a;
Node() { // 默认构造
a = 1;
b = 2;
c = 3;
}
Node(int a, int b, int c) { // 有参构造函数
this->a = a;
this->b = b;
this->c = c;
}
void displayAll() { // 成员函数
displayA();
displayB();
displayC();
}
void displayA();
private: // 私有
int b;
void displayB();
protected: // 保护
int c;
void displayC();
};
void Node::displayA() {
cout << a << endl;
}
void Node::displayB() {
cout << b << endl;
}
void Node::displayC() {
cout << c << endl;
}
int main() {
Node n;
n.displayAll();
return 0;
}
对象的复制(深拷贝)
注意,复制分为浅拷贝和深拷贝,浅拷贝就是简单的对象赋值,深拷贝是将对象所指向的值复制一份再进行赋值。
直接上代码
#include <iostream>
#include <cstring>
using namespace std;
class Node {
public:
char *a;
Node() {
a = new char[10];
strcpy(a, "hello");
}
Node(char *b) {
a = new char[10];
strcpy(a, b);
}
void display() {
cout << a << endl;
}
};
int main() {
Node n;
Node n2("world");
Node n3(n);
n3.a[3] = '5';
n.display();
n2.display();
n3.display();
return 0;
}
上述程序会输出以下结果
hel5o
world
hel5o
思考一下为什么?怎么解决?
上述程序进行的是浅拷贝, 就是你没有重载复制构造函数, 需要写出下面的形式。上下比较一下。
#include <iostream>
#include <cstring>
using namespace std;
class Node {
public:
char *a;
Node() {
a = new char[10];
strcpy(a, "hello");
}
Node(char *b) {
a = new char[10];
strcpy(a, b);
}
void display() {
cout << a << endl;
}
Node(const Node& n2) {
a = new char[10];
strcpy(a, n2.a);
}
};
int main() {
Node n;
Node n2("world");
Node n3(n);
n3.a[3] = '5';
n.display();
n2.display();
n3.display();
return 0;
}
上述程序会输出以下结果
hello
world
hel5o
静态成员
静态成员分为静态数据成员,和静态成员函数,静态成员函数无法访问非静态数据成员。
那么什么是静态,你可以这么理解,就是他不是动态的(哈哈),什么叫不是动态的,new知道嘛?动态申请资源,静态就是他不用动态申请,那既然不能动态申请(就是申请好几份,几百分,很多很多份),那说明静态的数据或者函数就只有一个。举个例子,太阳就是人的静态数据成员(人被太阳晒着),那人是不是无限增长的,是不是动态生成的?但是你指着太阳说今天太阳好大,和我指着太阳说师啊,太阳真大,指的是一个太阳还是二个太阳?理解了嘛?
直接上代码
#include <iostream>
using namespace std;
class Node {
public:
static int number; // 静态数据成员
Node() {
number++;
}
static void display() { // 静态成员函数
cout << number << endl;
}
};
int Node::number = 0; // 初始化
int main() {
Node n;
Node n2;
Node::display(); // 可以通过类名
n.display(); // 可以通过对象
return 0;
}
注意,静态数据成员需要初始化。
友元
友元有友元函数和友元类。
在这里,友元函数,就是这个函数可以访问被friend标记的类的所有数据和函数。
友元类就是这个类可以访问被friend标记的类的所有数据和函数。
注意 VC6.0有的时候不支持友元,会编译错误,去掉using namespace std;即可
#include <iostream>
using namespace std;
class Node2;
class Node {
public:
Node() {
number++;
}
friend void display(Node &t);
friend Node2;
private:
static int number;
};
class Node2 {
public:
void display(Node& n) {
cout << n.number << endl;
}
};
int Node::number = 0; // 初始化
void display(Node &t) {
cout << t.number << endl;
}
int main() {
Node n;
display(n);
return 0;
}