您的位置:首页 > 编程语言 > C语言/C++

c++一些入门基础,也是初学者容易卡住的地方

2017-10-09 11:31 417 查看
一:类和对象:

不说那么多官方概念,我认为类就是更高级于c语言的结构体。

因为它具有封装性,那么什么是封装?简单来说,类里不仅可以有变量,还可以有函数。



不过这个类是声明,不占空间,,像一个模型一样的东西,那么对象就是类的实例化!

我举个例子,如果会弹琴的朋友肯定知道看曲谱和真正弹奏的区别,那么类就是一个谱子,一个谱子可以弹奏多首曲子。

对象就是它的实例化,也就是弹出来这首曲子,曲子里有很多不同的音符,节奏,段落。

题外话:我副职业指弹吉他




以上是我个人的观点,觉得比较好理解,如果不对欢迎大神来更正。

刚才我说,c++更高级,他当然不是仅仅高级在类里可以写函数,还有很多东西需要慢慢学习。

.访问限定符:



那么来定义一个简单的类:

class Date
{
public:
void show()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

public:
int _year;
int _month;
int _day;
};

int main()
{
Date d1;//类实例化出对象
d1._year = 2017;
d1._month = 10;
d1._day = 9;
d1.show();

return 0;
}

通过sizeof(d1);得到d1的大小是12,它遵守内存对齐,那么难道成员函数不占空间吗?



注:空类的大小是1个字节,不是0,表示它存在,站位。

二:隐含的this指针:

1.每个成员函数(除了构造函数)都有一个指针形参,叫this,是隐含的。

2.在对象调用成员函数时,对象的地址作实参传递给成员函数的第一个指针形参。



三:默认成员函数:

1.构造函数:

无返回值

函数值与类名相同

对象实例化自动调用

可重载

如不定义,自动生成一个缺省的构造函数

无参,全缺省都认为是缺省构造函数,缺省的只能有一个。
class Date
{
public:
//Date()//无参
//{
//
//}

//Date(int year,int month,int day)//带参
//{
// this->_year = year;
// this->_month = month;
// this->_day = day;

// cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
//}

Date(int year = 2017,int month = 10,int day = 9)//缺省
{
this->_year = year;
this->_month = month;
this->_day = day;

cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

void show()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

private:
int _year;
int _month;
int _day;
};

int main()
{
Date d1(2017,10,1);
Date d2;

return 0;
}

d1后面得加括号,d2后面不能加,因为有可能被识别为其他函数。

2.拷贝构造函数:创建对象是用同类对象来初始化。

Date(const Date& d)
{
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
}定义了拷贝构造函数之后,

Date d1(2017,10,1);

Date d2(d2);//d2就和d1一样了。

d2的地址传给this,d1引用传递,否则会无穷递归,如图。



注意:必须用引用传参,不引用就会无穷递归,给d1加const。

如果未定义拷贝构造函数,会默认为值拷贝。(值拷贝有时候会有问题,比如有指针指向动态内存开辟的空间,如下)

3.析构函数:当一个对象生命周期结束,调用的成员函数,是清理工作。

类名前加~

无参数无返回值

一个类只有一个析构,未定义会自动生成缺省的

对象生命周期结束,自动调用。

接下来我写一个有指针指向动态内存开辟的空间。

class Seqlist
{
public:
Seqlist()
{
_a = (int*)malloc(sizeof(int)*5);
_size = 0;
_capacity = 5;
}

void PushBack(int x)
{
this->_a[(this->_size)++] = x;
}

void print()
{
for(size_t i = 0; i < this->_size; i++)
{
cout<<this->_a[i]<<endl;
}
}

Seqlist(const Seqlist& s)
{
int i = 0;
for(i = 0; i<s._size; i++)
{
this->_a[i] = s._a[i];
}
}

~Seqlist()
{
if(this->_a)
{
free(this->_a);
this->_a = NULL;
this->_size = 0;
this->_capacity = 0;
}
}

private:
int* _a;
size_t _size;
size_t _capacity;
};

int main()
{
Seqlist s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(4);
s1.print();

Seqlist s2 = s1;
s2.print();
}

显然这是一个简单的顺序表,实现了尾插的功能。

析构函数最后free掉了_a,并且把它指向NULL,看起来都没有问题,不过如果不写拷贝构造函数,而直接使用的话,会出现问题。



4.运算符重载:为了让自定义类型可以用运算符

operator+合法的运算符构成函数名。

注:c++5个不支持重载的运算符:  .*    ::     sizeof    ?:    .

举例:operator<

class Date
{
public:
Date(int year = 2017,int month = 10,int day = 9)
{
_year = year;
_month = month;
_day = day;

cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

bool operator<(const Date& d)
{
if(this->_year < d._year)
{
return true;
}
else if(this->_year == d._year)
{
if(this->_month < d._month)
{
return true;
}
else if(this->_month == d._month)
{
if(this->_day < d._day)
{
return true;
}
}
}
return false;
}

private:
int _year;
int _month;
int _day;
};

void test()
{
Date d1(2017,1,25);
Date d2(2017,1,27);

cout<<(d1<d2)<<endl;

}

int main()
{
test();
return 0;
}

将它写入类内当成成员函数,不然访问不了私有成员。

d1<d2,其实就是d1.operator(&d1,d2),d1的地址传给this,d2引用传递。



赋值运算符重载:

class Date
{
public:
Date(int year = 2017,int month = 10,int day = 9)
{
_year = year;
_month = month;
_day = day;

//cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}

return *this;
}

void show()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}

private:
int _year;
int _month;
int _day;
};

void test()
{
Date d1(2017,1,25);
Date d2(2017,1,27);

d2 = d1;
d2.show();
}

int main()
{
test();
return 0;
}

注:引用返回是为了能够连续赋值,比如:d1 = d2 =d3;

if是为了避免两日期相同还赋值浪费时间。

拷贝构造和赋值运算符重载的区别:

Date d4 = d3;//拷贝构造,用同类对象来创建。

d4 = d3;//赋值运算符重载,已存在的两对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 成员函数