私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。
在面向对象编程中,友元函数(friend function)是一个指定类(class)的“朋友”,该函数被允许访问该类中private、protected、public的数据成员。普通的函数并不能访问这些数据,然而宣告一个函数成为一个类的友元函数则被允许访问这些数据。
友元函数的宣告可以放在类声明的任何地方,不受访问限定关键字private、protected、public的限制。一个相似的概念是友谊类。
友谊关键字应该谨慎使用。如果一个拥有private或者protected成员的类,宣告过多的友元函数,可能会降低封装性的价值,也可能对整个设计框架产生影响。
不可否认,友元在一定程度上将类的私有成员暴露出来,破坏了信息隐藏机制,似乎是种“副作用很大的药”,但俗话说“良药苦口”,好工具总是要付出点代价的,拿把锋利的刀砍瓜切菜,总是要注意不要割到手指的。
友元的存在,使得类的接口扩展更为灵活,使用友元进行运算符重载从概念上也更容易理解一些,而且, C++ 规则已经极力地将友元的使用限制在了一定范围内,它是单向的、不具备传递性、不能被继承,所以,应尽力合理使用友元。
注意:友元的声明是不受 public/protected/private 关键字限制的。
1.不能无中生有(不能定义新的运算符),也不要改变运算符的原有意义。
2.重载不能改变运算符运算对象(即操作数)的个数。
3.重载不能改变运算符的优先级与结合性。
4.重载运算符的函数不能指定默认的参数值。
5.重载运算符函数的参数应至少有一个是类对象(或类对象的引用),不能都是基本类型。
作用域操作符:::
条件操作符:?:
点操作符:.
指向成员操作的指针操作符:->*,.*
还有 sizeof运算符
.、.*运算符不能重载是为了保证访问成员的功能不能被改变,域运算和sizeof运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。
私有成员体现了封装性的特点,而静态全局变量只是起到了一个计数的作用,是共享的。除此之外,func函数只是在逻辑顺序上的执行,而fo可以无限的创建,函数对象可以体现出状态。
一般地,把这种带有状态的函数对象成为闭包—>匿名函数—>lambda表达式
在C++对下标访问运算符重载的好处
1.增加 安全性,对下标进行判断,相比C里面数组安全
2.重载【】之后,可以放在等号的左边
在什么情况下,需要加引用符号
1.防止返回值是对象的时候调用拷贝构造函数
2.允许连续赋值的时候,cout << “hello” << endl;
1.运算符重载之普通函数形式进行重载
2.运算符重载之成员函数
3.运算符重载之友元函数的形式进行重载(可以直接对类的私有成员进行操作,非常方便,并且符合加法的习惯,两个操作数,没有采用隐藏this指针的方式,只有一个操作数出现,不符合加法习惯,推荐使用以友元函数的形式进行重载)
特别地,如果以自身状态为改变目标的重载,可以以成员函数的形式进行重载,比较方便。比如这里+=, -=, /=都可以以这种成员函数方式进行重载。
非常清晰,后置++首先要把表达式的值保存下来,之后对成员变量进行++,然后返回保存下来的表达式的值,注意顺序。其中后置++中参数列表中有一个int,这只表示着,后置++的一个标示,不代表传参。这是实现c++的大佬写的,大佬就是规则的制定者,记住吧少年
这里com是一个局部变量,所以要注意千万不要返回引用,这里要把引用去掉。
这里也可以看得出,前置++和后置++是有区别的,前置++的效率都说效率很高,因为前置++返回的是一个引用,是对象本身。后置++返回的是一个局部对象,包含一个执行拷贝构造函数的过程,所以相比下来,效率就比前置++的 执行效率低。
看一个有意思的左值和右值
前置++返回的是对象本身,所以可以加取地址符号,是左值。
而后置++返回的是一个局部变量,是右值。
运算符重载代码:
#include
#include
#include
using std::cin;
using std::endl;
using std::cout;
using std::cerr;
using std::vector;
class String {
public:
String()
: _pstr(nullptr)
{
cout << "String()" << endl;
}
String(const char *pstr)
{
cout << "String(const char*)" << endl;
_pstr = new char[strlen(pstr) + 1];
strcpy(_pstr, pstr);
}
String(const String &pstr){
cout << "String(const String&)" << endl;
_pstr = new char[strlen(pstr._pstr) + 1];
strcpy(_pstr, pstr._pstr);
}
~String(){
cout << "~String()" << endl;
if(_pstr != nullptr){
delete _pstr;
_pstr = nullptr;
}
}
void display() const
{
cout << _pstr << endl;
}
String &operator=(const String &);
String &operator=(const char *);
String &operator+=(const String &);
String &operator+=(const char *);
char &operator[](std::size_t index);
const char &operator[](std::size_t index) const;
size_t size() const;
const char* c_str() const;
friend bool operator==(const String &, const String &);
friend bool operator!=(const String &, const String &);
friend bool operator<(const String &, const String &);
friend bool operator>(const String &, const String &);
friend bool operator<=(const String &, const String &);
friend bool operator>=(const String &, const String &);
//杈撳叆杈撳嚭娴佺殑鍙互鍙傝€冩暀鏉愶紝
friend std::ostream &operator<<(std::ostream &os, const String &s);
friend std::istream &operator>>(std::istream &is, String &s);
private:
char *_pstr;
};
size_t String::size() const
{
return strlen(_pstr);
}
const char* String::c_str() const
{
return &_pstr[0];
}
String &String::operator=(const String &str){
cout << "String &String::operator=(const String &)" << endl;
if(strcmp(_pstr, str.c_str())){
_pstr = new char[strlen(str._pstr) + 1];
strcpy(_pstr, str._pstr);
}
return *this;
}
String &String::operator=(const char *str){
cout << "String &String::operator=(const char*)" << endl;
if(_pstr){
delete _pstr;
_pstr = nullptr;
}
_pstr = new char[strlen(str) + 1];
strcpy(_pstr, str);
return *this;
}
String &String::operator+=(const String &str){
cout << "String &String::operator+=(const String&)" << endl;
size_t length1 = this->size();
size_t length2 = str.size();
const char *s = this->c_str();
_pstr = new char[length1 + length2 + 1];
strcpy(_pstr, s);
strcat(_pstr, str._pstr);
return *this;
}
String &String::operator+=(const char *str){
cout << "String &String::operator+=(const char*)" << endl;
size_t length1 = this->size();
size_t length2 = strlen(str);
const char *s = this->c_str();
_pstr = new char[length1 + length2 + 1];
strcpy(_pstr, s);
strcat(_pstr, str);
return *this;
}
char &String::operator[](std::size_t index){
if(index < 0 && index > size()){
static char p= '\0';
cerr << "wrong index" << endl;
return p;
}
else{
return _pstr[index];
}
}
const char &String::operator[](std::size_t index) const
{
if(index < 0 && index > size()){
static char p= '\0';
cerr << "wrong index" << endl;
return p;
}
else{
return _pstr[index];
}
}
bool operator==(const String &lhs, const String &rhs){
if(!strcmp(lhs._pstr, rhs._pstr)){
return true;
}
return false;
}
bool operator!=(const String &lhs, const String &rhs){
if(strcmp(lhs._pstr, rhs._pstr)){
return true;
}
return false;
}
bool operator<(const String &lhs, const String &rhs){
size_t length1 = strlen(lhs._pstr);
size_t length2 = strlen(rhs._pstr);
size_t index = 0;
while(length1 && length2){
if(lhs[index] < rhs[index]){
return true;
}
index++;
}
if(index != length2){
return true;
}
return false;
}
bool operator>(const String &lhs, const String &rhs){
size_t length1 = strlen(lhs._pstr);
size_t length2 = strlen(rhs._pstr);
size_t index = 0;
while(length1 && length2){
if(lhs[index] > rhs[index]){
return true;
}
index++;
}
if(index != length1){
return true;
}
return false;
}
bool operator<=(const String &lhs, const String &rhs){
if(lhs == rhs || lhs < rhs){
return true;
}
return false;
}
bool operator>=(const String &lhs, const String &rhs){
if(lhs == rhs || lhs > rhs){
return true;
}
return false;
}
String operator+(const String &lhs, const String &rhs){
char *p;
strcpy(p, lhs.c_str());
strcat(p, rhs.c_str());
String str = p;
return str;
}
String operator+(const String &string, const char *str){
char *p;
strcpy(p, string.c_str());
strcat(p, str);
String s = p;
return s;
}
String operator+(const char *str, const String &string){
char *p;
strcpy(p, str);
strcat(p, string.c_str());
String s = p;
return s;
}
std::ostream &operator<<(std::ostream &os, const String &s){
os << s._pstr;
return os;
}
std::istream &operator>>(std::istream &is, String &s){
/* is >> s._pstr; */
/* if(!is){ */
/* s = "oops"; */
/* } */
/* return is; */
if(s._pstr){
delete [] s._pstr;
s._pstr = nullptr;
}
vector<char> buffer;
char ch;
while((ch = is.get()) != '\n'){
buffer.push_back(ch);
}
s._pstr = new char[buffer.size() + 1]();
strncpy(s._pstr, &buffer[0], buffer.size());
}
int main()
{
String str1("hello world");
cout << "str1 = ";
str1.display();
cout << endl;
String str2(str1);
cout << "str2 = ";
str2.display();
cout << endl;
String str3("nihao");
cout << "str3---before change = ";
str3.display();
str3 = str2;
cout << "str3---after change = ";
str3.display();
cout << endl;
char *s = (char *)"sayounala";
String str4 = s;
cout << "str4 = ";
str4.display();
cout << endl;
String str5("baby");
cout << "str5 = ";
str5.display();
str5 += str4;
cout << "str5 = ";
str5.display();
cout << endl;
String str6("baobao");
cout << "str6 = ";
str6.display();
str6 += s;
cout << "str6 = ";
str6.display();
cout << endl;
String a = "123";
String b = "123";
String c = "1234";
String d = "234";
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
cout << "d = " << d << endl;
String e;
cout << "Plz input a number:";
cout << endl;
cin >> e;
cout << "e = " << e << endl;
cout << "(a == b) = " << (a == b) << endl;
cout << "(a == c) = " << (a == c) << endl;
cout << "(a != c) = " << (a != c) << endl;
cout << "(a > c) = " << (a > c) << endl;
cout << "(a < c) = " << (a < c) << endl;
cout << "(a < d) = " << (a < d) << endl;
cout << "(a > d) = " << (a > d) << endl;
return 0;
}