一、public、protected和private
C++类中有三个关键词:public、private和protected,主要是限定对类内数据的访问权限:
- public:可以被该类中的函数,子类的函数,其友元函数访问,也可以在该类外访问。
- protected:可以被该类中的函数,子类的函数,其友元函数访问。
- private:只能由该类中的函数,其友元函数访问。
具体如下:
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
int data1;
int data2;
protected:
int data3;
int data4;
private:
int data5;
int data6;
};
int main() {
A a(1, 2);
cout << "outof class a, data access: " << endl \
<< "data1: " << a.data1 << endl \
<< "data2: " << a.data2 << endl;
return 0;
}
结果如下:
outof class a, data access:
data1: 1
data2: 2
如果把数据换成data3,data4,data5,data6会报错,所以在类外只能够访问public成员。
对于类的成员函数
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
void print_public(){
cout << "public function member" << endl;
}
int data1;
int data2;
protected:
int data3;
int data4;
void print_protected(){
cout << "protected function member" << endl;
}
private:
int data5;
int data6;
void print_private(){
cout << "private function member" << endl;
}
};
int main() {
A a(1, 2);
a.print();
return 0;
}
类外可以访问public成员函数,所以在类外只能够访问public成员。
那么成员函数访问有权限吗?没有,成员函数可以访问类的任意数据。
那么静态成员函数呢?
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
static void print1(A a) {
cout << "outof class a, data access: " << endl \
<< "data1: " << a.data1 << endl \
<< "data2: " << a.data2 << endl;
cout << "outof class a, data access: " << endl \
<< "data3: " << a.data3 << endl \
<< "data4: " << a.data4 << endl;
cout << "outof class a, data access: " << endl \
<< "data5: " << a.data5 << endl \
<< "data6: " << a.data6 << endl;
}
int data1;
int data2;
protected:
int data3;
int data4;
static void print2(A a) {
cout << "outof class a, data access: " << endl \
<< "data1: " << a.data1 << endl \
<< "data2: " << a.data2 << endl;
cout << "outof class a, data access: " << endl \
<< "data3: " << a.data3 << endl \
<< "data4: " << a.data4 << endl;
cout << "outof class a, data access: " << endl \
<< "data5: " << a.data5 << endl \
<< "data6: " << a.data6 << endl;
}
private:
int data5;
int data6;
static void print3(A a) {
cout << "outof class a, data access: " << endl \
<< "data1: " << a.data1 << endl \
<< "data2: " << a.data2 << endl;
cout << "outof class a, data access: " << endl \
<< "data3: " << a.data3 << endl \
<< "data4: " << a.data4 << endl;
cout << "outof class a, data access: " << endl \
<< "data5: " << a.data5 << endl \
<< "data6: " << a.data6 << endl;
}
};
int main() {
A a(1, 2);
A::print1(a);
// A::print2(a); 错误,不能访问print2
// A::print1(a); 错误,不能访问print3
return 0;
}
虽然static不属于任何一个类,但是对于protected和private类外依然不能访问。还有static函数不属于类成员所以,需要传递参数,没有隐式传递this指针。
二、友元
2.1友元函数
声明友元函数可以访问类的protected成员和private成员,但是同样友元函数不属于类。因为和静态函数一样,不会默认传入this指针。
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
friend void print_frined(A a);
int data1;
int data2;
protected:
int data3;
int data4;
private:
int data5;
int data6;
};
void print_frined(A a){
cout << "outof class a, data access: " << endl \
<< "data1: " << a.data1 << endl \
<< "data2: " << a.data2 << endl;
cout << "outof class a, data access: " << endl \
<< "data3: " << a.data3 << endl \
<< "data4: " << a.data4 << endl;
cout << "outof class a, data access: " << endl \
<< "data5: " << a.data5 << endl \
<< "data6: " << a.data6 << endl;
}
int main() {
A a(1, 2);
print_friend(a);
return 0;
}
输出结果
outof class a, data access:
data1: 1
data2: 2
outof class a, data access:
data3: 1
data4: 2
outof class a, data access:
data5: 1
data6: 2
2.2 友元类成员函数
在此之前记录一下c++前置声明的问题(太扯淡了,这么离奇的问题竟然现在才知道,我不愧是个大菜鸡)
和友元函数不一样的是,友元类成员函数,这个函数是另一个类的成员函数,但是访问权限都一样,如下:
class A;
class B{
public:
void visit(A* a);
};
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
friend void B::visit(A* a);
int data1;
int data2;
protected:
int data3;
int data4;
private:
int data5;
int data6;
};
void B::visit(A* a){
cout << "outof class a, data access: " << endl \
<< "data1: " << a->data1 << endl \
<< "data2: " << a->data2 << endl;
cout << "outof class a, data access: " << endl \
<< "data3: " << a->data3 << endl \
<< "data4: " << a->data4 << endl;
cout << "outof class a, data access: " << endl \
<< "data5: " << a->data5 << endl \
<< "data6: " << a->data6 << endl;
}
int main() {
A a(1, 2);
B b;
b.visit(&a);
return 0;
}
注意:B类之前要前置声明A,B的visit函数参数只能使用指针或者引用,B::visit函数的实现必须在A类定义完之后。
输出结果如下:
outof class a, data access:
data1: 1
data2: 2
outof class a, data access:
data3: 1
data4: 2
outof class a, data access:
data5: 1
data6: 2
B的成员函数可以访问A的所有成员。
2.3 友元类
简单来说就这样
#include <iostream>
using namespace std;
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
int data1;
int data2;
friend class B;
protected:
int data3;
int data4;
private:
int data5;
int data6;
};
class B {
public:
int data0 = 0;
void visit(A* a);
private:
int data1 = 1;
};
void B::visit(A* a) {
cout << "outof class A, data access: " << endl \
<< "data1: " << a->data1 << endl \
<< "data2: " << a->data2 << endl;
cout << "outof class A, data access: " << endl \
<< "data3: " << a->data3 << endl \
<< "data4: " << a->data4 << endl;
cout << "outof class A, data access: " << endl \
<< "data5: " << a->data5 << endl \
<< "data6: " << a->data6 << endl;
}
int main() {
A a(1, 2);
B b;
b.visit(&a);
return 0;
}
运行结果如下:
outof class A, data access:
data1: 1
data2: 2
outof class A, data access:
data3: 1
data4: 2
outof class A, data access:
data5: 1
data6: 2
然而,c++里友元不是双向的,这就是说,在A中声明:B是A的友元,B中的所有方法可以访问A的所有成员,但是A不能访问B的所有成员。
#include <iostream>
using namespace std;
class B;
class A {
public:
A(int a, int b) : data1(a), data2(b),
data3(a), data4(b), data5(a), data6(b) {}
~A() {}
void visit(B* b); // A新加的函数
int data1;
int data2;
friend class B;
protected:
int data3;
int data4;
private:
int data5;
int data6;
};
class B {
public:
int data0 = 0;
void visit(A* a);
private:
int data1 = 1;
};
// 新加的东西
void A::visit(B* b) {
cout << b->data0 << endl;
//cout << b->data1 << endl; // 报错
}
void B::visit(A* a) {
cout << "outof class A, data access: " << endl \
<< "data1: " << a->data1 << endl \
<< "data2: " << a->data2 << endl;
cout << "outof class A, data access: " << endl \
<< "data3: " << a->data3 << endl \
<< "data4: " << a->data4 << endl;
cout << "outof class A, data access: " << endl \
<< "data5: " << a->data5 << endl \
<< "data6: " << a->data6 << endl;
}
int main() {
A a(1, 2);
B b;
b.visit(&a);
return 0;
}
注意:前置声明和成员函数实现的位置。如果A企图访问B的私有成员数据data1,编译器会报错。