从Java面向对象过渡到c++面向对象
1. 对象的定义
/*
* c++ namespace 修饰符
* 创建对象的两种方式
* 释放堆上对象内存
* 类外独立函数main()
* this指针
*
*/
// c++ input output stream
#include<iostream>
// c++命名空间,作用域
// 命名空间(namespace)为防止名字冲突提供了更加可控的机制。命名空间分割了全局命名空间,其中每个命名空间是一个作用域。
// 通过在某个命名空间中定义库的名字,库的作者以及用户可以避免全局名字固有的限制。
using namespace std;
// c++ class前没有修饰符
class A
{
// 若成员变量不加修饰符,默认为private
// c++类成员修饰符格式为"private:"
private:
int x;
public:
void setX(int x)
{
// this是指针,而不是引用
this->x = x;
}
int getX()
{
return this->x;
}
};
// c++函数可以孤立、声明在类外
int main(int argc, char *argv[])
{
// 创建对象的两种方式
// 为节省存储空间,C++创建对象时仅分配用于保存数据成员的空间,而类中定义的成员函数则被分配到存储空间中的一个公用区域,由该类的所有对象共享。
// 内存分配是分配到栈中的,由C++缺省创建和撤销,自动调用构造函数和析构函数
A a;
// 在堆上分配内存来创建对象的(与上不同);不同的是,C++用new创建对象时返回的是一个对象指针。
A *a1=new A;
a.setX(0);
(*a1).setX(1);
// cout 打印到控制台
cout<<a.getX()<<" "<<(*a1).getX()<<endl;
// 用new动态创建的对象必须用delete来撤销该对象。只有delete对象才会调用其析构函数。
delete a1;
return 0;
}
2.构造函数、析构函数、拷贝构造函数
/*
* c++构造函数、析构函数、拷贝构造函数
*
*/
#include<iostream>
using namespace std;
class A
{
public:
// 构造函数、析构函数、拷贝构造函数名必须与类名相同
// 为了区分构造函数与析构函数,在析构函数前加“~”
// 一个类只能有一个析构函数,析构和函数不能有参数
// 编译器会自动生成无参构造函数和拷贝构造函数
// 无参构造函数
A() { cout<<"调用无参构造函数"<<endl; }
// 有参构造函数
A(int x, int y) { cout<<"调用有参构造函数"<<endl; }
// 拷贝构造函数
A(const A &a) { cout<<"调用拷贝构造函数"<<endl; }
// 析构函数
~A() { cout<<"调用析构函数"<<endl; }
};
int main(int argc, char *argv[])
{
A a1;
A a2(0,1);
// 自动调用拷贝构造函数
// A a3(a1);是一样的
A a3=a1;
A *a4=new A;
delete a4;
return 0;
}
3. 三种继承方式与多继承
/*
* c++ 三种继承方式与多继承
*
*/
using namespace std;
class A
{
private:
int x;
protected:
int y;
public:
int z;
};
/*
* 公有继承方式
* x不能被继承,y、z访问权限不变
* 与java中的继承方式相同
*/
class B:public A { };
/*
* 保护继承
* x不能被继承,y访问权限不变,z变为protected
* 限制了子类的成员访问权限
*/
class C:protected A { };
/*
* 私有继承
* x不能被继承,y、z访问权限都变为private
*/
class D:private A { };
class A1 { };
/*
* 多继承
*/
class E:public A,public A1 { };
int main(int argc, char *argv[])
{
return 0;
}
4.友元函数与友元类
/*
* c++ friend function and class
* 友元关系不具有传递性,它是单向的,不能被继承
* 可见,复杂的友元关系被限制地较为简单
*
*/
#include<iostream>
using namespace std;
class A
{
private:
int x;
public:
A() { x=0; }
// 友元函数,可以是另一个类的函数,也可以是独立函数,但不能是本类函数
// friend关键字修饰
friend void fun(A &a);
// 友元类
friend class B;
};
class B
{
public:
// &a 表示传入A对象的引用
B(A &a)
{
cout<<"A的友元类创建一个对象"<<endl;
cout<<"A的私有成员变量x="<<a.x<<endl;
}
};
void fun(A &a)
{
cout<<"A 调用了它的友元函数fun()"<<endl;
cout<<"A的私有成员变量x="<<a.x<<endl;
}
int main(int argc, char *argv[])
{
A a;
fun(a);
B b(a);
return 0;
}
5.虚函数
/*
* c++ 虚函数
* 虚函数为派生类可以重写的函数
* 虚函数可以被继承,且在派生类中不必再使用virtual关键字重新声明
* 利用虚函数可以定义类似java中的接口和抽象类
*
*/
using namespace std;
class A
{
public:
// 只有这三种函数可以加virtual修饰符,其余函数不能,
// 如非类成员函数、静态成员函数、构造函数不能加virtual
// 普通虚函数,基类有函数体
virtual void fun1() { }
// 纯虚函数,其类没有函数体,用“=0”表示
virtual void fun2()=0;
// 虚析构函数
virtual ~A() { }
};
class B:public A
{
public:
// 这些函数依然是虚函数
void fun1() { }
void fun2() { }
~B() { }
};
int main(int argc, char *argv[])
{
// 含有纯虚函数的类不能创建对象
// A a;
B b;
return 0;
}
6.操作符重载
/*
* c++ 操作符重载
* 以++为例,有x++与++x之分
* java中其实也有操作符重载的,如字符串操作+、+=,但不能自定义
*
*/
using namespace std;
class A
{
public:
// 两种方式用一个int参数加以区分
// 后置++重载
void operator ++(int flag) { }
// 前置++重载
void operator ++() { }
};
int main(int argc,char *argv[])
{
A a;
a++;
++a;
return 0;
}