1.面向对象的三大特征: 封装,继承和派生,多态性 封装: 封装:(Encapsulation)是面向对象程序设计最基本的特性,把数据(属性)和函数(方法,操
作)合成一个整体,这在计算机世界中是用类与对象实现的。
继承(inheritance)机制:是类型层次结构设计中实现代码的复用重要手段。
派生:保持原有类特性的基础上进行扩展,增加新属性和新方法,从而产生新的类型。
在面向对象程序设计中,继承和派生是构造出新类型的过程。呈现类型设计的层次结构,体现了程序设计人员对现实世界由简单到复杂的认识过程。
class student : person // 冒号后没有属性默认是私有。
struct student : person // 冒号后没有属性默认是公有。
using namespace std;
class person
{
private:
int id ;
public:
char name[10];
protected:
int age;
public:
person(int x,const char * y,int z):id(x),age(z)
{
strcpy_s(name, strlen(y)+1, y);
cout << "Create person " << endl;
}
~person()
{}
void fun()
{
cout << "人跳舞" << endl;
}
void print()
{
cout << "name " <<name<<"age "<<age << endl;
}
};
class student : person
{
private:
int id;
public:
char name[10];
protected:
int sex;
public:
student(int x,const char * y,int z):person(202207,"ss",22),id(x),sex(z)
{
strcpy_s(name, strlen(y) + 1, y);
cout << "Create stundet" << endl;
}
student() :person(202207, "ss", 22), name(), sex()
{
cout << "Create stundet" << endl;
}
~student() {}
void print()
{
cout << " name :"<<name<<" sex :" << sex <<" id : " <<id <<endl;
cout << " name :" << person::name << " age :" << person::age << endl;
//cout << "person id :" <
}
};
int main()
{
person person1(202201,"yhping",12);
student student1(202002,"lmy",1);
student1.print();
}
student(int x,const char * y,int z):person(202207,"ss",22),id(x),sex(z) {} 中基类无名对象person也可以不初始化 :----> person(id,name,age)
- 在类型的继承层次结构中,保护属性当作公有属性来使用。
- 继承性具有传递性。
- 无论采取何种继承方式,派生类对象的成员方法都可以去访问基类对象中的保护和公有属性!!!!!!!!!!!!!!!!!!!!!!!!!!!。
那怎么可以访问基类的私有属性呢?
我们可以通过调动派生类对象的方法,在里面再去调动person类的方法。
class person
{
private:
int p1 ;
public:
char p2[10];
int weight=90;
protected:
int p3;
public:
void fun1()
{
p1 = 19940811;
p3 = 180;
}
const int& get_p1()const
{
return p1;
}
};
class student : public person
{
private:
int id;
person person_one;
public:
char name[10];
int high;
protected:
int sex;
public:
int get_p1()const
{
return id;
}
void fun()
{
const char* p = "zhangsanfeng";
person_one.weight = 1000;
strcpy_s(person::p2, strlen(p) + 1, p);
person::fun1();//通过fun1()的方法去访问私有属性
int val=person::get_p1();//通过此方法得到私有属性的值。
printf("%d", val);
}
};
int main()
{
person person1(202201,"yhping",12);
student student1(202002,"lmy",1,person1);
student1.high = 180;
student1.fun();
}
用fun函数初始化基类的person对象(注意不是student类里的基类person)
student(int x,const char * y,int z):person(id,name,age),id(x),sex(z)//这里的id,name,age 的是一个变量,不是person的属性!
{
strcpy_s(name, strlen(y) + 1, y);
cout << "Create stundet" << endl;
}
void fun()
{
//person::id = 2008;
const char* p = "zhangsanfeng";
strcpy_s(person::name, strlen(p) + 1, p);
person::age = 18;
}
void fun()
{
person::id = 2008;
const char* p = "zhangsanfeng";
strcpy_s(person::name, strlen(p) + 1, p);
person::age = 18;
}
这里看看能不能访问私有id的属性;(不可访问)
using namespace std;
class person
{
private:
int p1 ;
public:
char p2[10];
protected:
int p3;
public:
};
class student : public person
{
private:
int id;
public:
char name[10];
protected:
int sex;
public:
void fun()
{
//person::p1 = 987654; //无法访问p1
const char* p = "zhangsanfeng";
strcpy_s(person::p2, strlen(p) + 1, p);
person::p3 = 18;
}
};
int main()
{
person person1(202201,"yhping",12);
student student1(202002,"lmy",1);
person1.fun1();
student1.print();
}
我们准备访问student中基类(person)的保护属性和student类中的对象(person_one)属性中的保护属性( p 3 ),观察是否都能访问。
class person
{
private:
int p1 ;
public:
char p2[10];
protected:
int p3;
public:
person(int x,const char * y,int z):p1(x),p3(z)
{
strcpy_s(p2, strlen(y)+1, y);
cout << "Create person " << endl;
}
{}
};
class student : public person
{
private:
int id;
public:
char name[10];
person person_one;
protected:
int sex;
public:
student(int x,const char * y,int z,person &s1):person(x,y,z),id(x),sex(z),person_one(s1)
{
strcpy_s(name, strlen(y) + 1, y);
cout << "Create stundet" << endl;
}
void print()
{
//cout << " name2 :"<
cout << " person继承 p3(保护) :" << p3 << endl;
cout << " person_one属性 p2(公有) "<<person_one.p2 << endl;
}
};
int main()
{
person person1(202201,"yhping",12);
student student1(202002,"lmy",1,person1);
student1.print();
}
我们可以看到,继承来的person可以访问保护属性,student类里的person_one成员属性中的公有也可访问。
但是唯独student类里的person_one成员属性中的保护和私有是不可访问的。
1基类的可访问性控制
无论采取何种继承方式,派生类对象的成员方法都可以去访问基类对象中的保护和公有属性。外部 “.”(点)+属性的方式无法访问基类。
2.类类型的可访问性控制
(对于类类型来说,不管其属性是公有私有还是保护,设置的作用是控制外部对其访问的权限。对内部来说,无论采取何种继承方式,保护和私有都是不可访问的。)
3怎么访问私有属性?(不管继承类型是私有和保护都可行)()
无论是内部还是外部都需要调动成员方法才能改私有属性。
“不管其属性是公有私有还是保护,设置的作用是控制外部对其访问的权限”这句话举个例子:
class person
{
private:
int p1 ;
public:
char p2[10];
int weight=90;
protected:
int p3;
};
class student : private person
{
private:
int id;
public:
char name[10];
int high;
person person_one;
protected:
int sex;
public:
student(int x,const char * y,int z,person &s1):person(x,y,z),id(x),sex(z),person_one(s1)
{
strcpy_s(name, 10, y);
cout << "Create stundet" << endl;
}
void fun()
{
const char* p = "zhangsanfeng";
printf("%d", person_one.weight);
}
};
int main()
{
person person1(202201,"yhping",12);
student student1(202002,"lmy",1,person1);
student1.fun();
student1.person_one.weight = 0;//ok
student1.person_one.p3= -1;//error
}
person_one的属性如果是protected,那么student1.person_one.weight = 0;也是无法通过的。
3.同名隐藏(成员属性和成员方法)。(就近原则的机制,会调动离自己最近的成员方法。)
using namespace std;
#if 1
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x) {}
~Object() {}
void print(int x)
{
value = x;
cout << value << endl;
printf("OBJECT");
}
};
class Base : public Object
{
public:
int value;
public:
Base(int x = 0) : Object(x), value(x + 10) {}
~Base() {}
void print()
{
value += 10;
Object::value += 10;
printf("BASE");
}
};
int main()
{
Base base(100);
base.print();
//base.Object::print(10);
return 0;
}
结果输出是“BASE”
另一种情况:
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x) {}
~Object() {}
void print(int x)
{
value = x;
cout << value << endl;
printf("OBJECT");
}
};
class Base : public Object
{
public:
int value;
public:
Base(int x = 0) : Object(x), value(x + 10) {}
~Base() {}
void print()
{
value += 9;
Object::value += 10;
printf("BASE");
}
};
int main()
{
Base base(100);
base.print(10);//error
return 0;
}
我们想进行函数的重载那样进行类同名方法的重载,可现实确不被允许。
想调用基类的方法可以这样:base.Object::print(10);
C++面向对象编程中一条重要的规则是:公有继承意味着 “是一个” 。一定要牢牢记住这条规则。
1.赋值的切片
派生类的对象可以赋值给基类的对象,这时是把派生类对象中从对应基类中继承来的隐藏对象赋值 给基类对象。反过来不行,因为派生类的新成员无值可赋。
基类object 受保护,不能对其赋值,不能将地址赋
注意:赋值性规则2条:只能把子给给父 2.只能是公有类型!
class Object
{
public:
int value;
public:
Object(int x ) :value(x) {}
~Object() {}
void print()
{
cout <<"OBJECT"<< value << endl;
}
};
class Base : public Object
{
public:
int num;
public:
Base(int x = 0) : Object(x), num(x + 10) {}
~Base() {}
void print()
{
cout << "base.value"<<value << endl;
}
};
int main()
{
Base base(100);
Object object(1000);
//object = base;//切片现象。
object.print();
base.print();
return 0;
}
而赋值会产生切片现象,即把基类的属性值赋值给基类对象的属性值。而子对象派生的属性不会赋值出去。
举个例子,人对象和学生对象,学生是人,人不一定是学生。从世界实际来说父赋值给子是不成立的。第二,新派生的值没有办法给。
2.传地址和引用的切片
问:类型对指针的约束能力?
1.指针加一的能力 ,2。指针解析的能力
Base base(100);
Object object(1000);
Object* p = &base;
Object& ip = base;
ip.value = 999;
cout << ip.value << endl;
return 0;
Object* p = &base; // obj在解引用时只能解析到看到的4字节空间,所以解析不到base 派生的num的值。