二、面向对象的基本概念

2020-10-24  本文已影响0人  silasjs

结构化程序设计

在结构化程序设计中,采用自顶向下逐步求精模块化的思想,将复杂的大问题层层分解为许多简单的小问题。

在编写程序时,使用3中基本控制结构来构造程序。可以说,程序基本上都含有顺序选择循环3中基本控制结构,这3中控制结构到目前为止仍然是只要的控制结构。程序以控制结构为单位,只有一个入口和一个出口,基于控制结构可以从前往后的顺序阅读程序,程序的静态描述与执行时的控制流程容易对应,所以可以独立的理解各个部分。结构化程序设计主要强调的是程序的易读性。

面向对象程序设计的概念和特点

概念

特点

类的初步知识

类的定义

名称 描述 代表
成员变量 是类中的一类成员,
个数不限,
也称为数据成员。
成员变量的声明方式与普通变量的声明相同。
代表对象的属性
成员函数 是类中的另一类成员,
个数不限,
其声明方式与普通函数的声明相同。
代表对该类对象所含数据
进行操作的方法。

示例

myDate

class myDate {
public:
    myDate();                      //构造函数
    myDate(int, int, int);         //构造函数
    void setDate(int, int, int);   //设置日期
    void setDate(myDate);          //设置日期
    myDate getDate();              //获取日期
    void setYear(int);             //设置年
    int getMonth();                //设置月
    void printDate() const;        //打印日期
private:
    int year, month, day;          //成员变量
};

myDate::myDate() {
    year = 1970;
    month = 1;
    day = 1;
}
myDate::myDate(int y, int m, int d) {
    year = y;
    month = m;
    day = d;
}
void myDate::setDate(int y, int m, int d) {
    year = y;
    month = m;
    day = d;
}
void myDate::setDate(myDate date) {
    year = date.year;
    month = date.month;
    day = date.day;
}
myDate myDate::getDate() {
    return *this;
}
void myDate::setYear(int y) {
    year = y;
}
int myDate::getMonth() {
    return month;
}
void myDate::printDate() const {
    cout << year << "年" << month << "月" << day << "日" << endl;
}

Student

class Student {
public:
    Student();
    Student(string, myDate);
    string _nickname;
    void setStudent(string, myDate);
    void setName(string);
    string getName();
    void setBirthday(myDate);
    myDate getBirthday();
    void printStudent() const;
private:
    string _name;
    myDate _birthday;
};

Student::Student() {
    _name = "xxx";
    _nickname = "nickname";
    _birthday = myDate(1970, 1, 1);
}
Student::Student(string name, myDate birthday) {
    _name = name;
    _nickname = "nickname";
    _birthday = birthday;
}
void Student::setStudent(string name, myDate birthday) {
    _name = name;
    _birthday = birthday;
}
void Student::setName(string name) {
    _name = name;
}
string Student::getName() {
    return _name;
}
void Student::setBirthday(myDate birthday) {
    _birthday = birthday;
}
myDate Student::getBirthday() {
    return _birthday;
}
void Student::printStudent() const {
    cout << "姓名:" << _name << ", 昵称 = " << _nickname << ", 生日:";
    _birthday.printDate();
    cout << endl;
}

main函数

#include <iostream>

#include "myDate.hpp"
#include "Student.hpp"

using namespace std;

int main(int argc, const char * argv[]) {
    string name;
    int y, m, d;
    
    cout << "请输入学生的姓名和生日,以\"年月日\"的顺序输入" << endl;
    cin >> name >> y >> m >> d;
    
    Student s = Student();
    s.setStudent(name,
                 myDate(y, m, d));
    s.printStudent();
    
    return 0;
}

类的示例程序剖析

程序结构

成员变量与成员函数的定义

实现成员函数时要指明类的名称,在类体外定义的一般格式如下:

返回值类型 类名::成员函数名(参数列表) {
    成员函数的函数体
}

成员函数并非每个对象各自存有一份。成员函数和普通函数一样,在内存中只有一份,它可以作用域不同的兑现个,为类中各对象共享

通常,因为函数体代码较长,所以在类体内仅给出成员函数的原型,然后在类体外给出对应的函数体。如果函数体定义在类体内,则系统将其视为内联函数。类中定义的成员函数允许重载。

创建类对象的基本形式

void create() {
    //类名 对象名;
    Student s;
    
    //类名 对象名(参数);
    myDate birthday(2020, 5, 25);
    
    //类名 对象名 = 类名(参数);
    Student s1 = Student("邓紫棋", birthday);
   
    //可以扩展为多个对象
    //类名 对象名1, 对象名2, 对象名3,...;
    Student s2, s3, s4;
    //类名 对象名1(参数), 对象名2(参数),...;
    Student s5("王五", birthday), s6("赵六", birthday);
    
    //类名 *对象名 = new 类名;
    Student *s8 = new Student;
    
    //类名 *对象名 = new 类名();
    Student *s9 = new Student();
    
    //类名 *对象名 = new 类名(参数);
    Student *s10 = new Student("十号", birthday);
}

new创建对象时返回的是一个对象指针,这个指针指向本类刚创建的这个对象。C++分配给指针的仅仅是存储指针值的空间,而对象所占用的空间分配在堆上。使用new创建的对象,必须用delete来撤销。

与基本数据类型一样,还可以声明对象的引用、对象的指针及对象数组。

void create1() {
    Student s = Student("永桂",
                        myDate(1999, 9, 9));
    
    //声明对象引用,即变量别名
    Student &yonggui = s;
    
    //声明对象的指针
    Student *yg = &yonggui;
    
    //声明对象数组的形式
    Student students[5];
}

同类型的对象之间可以相互赋值。对象和对象指针都可以用作函数参数。函数的返回值可以是对象或指向对象的指针。

访问对象的成员

void visit() {
    Student s = Student();
    
    //1.通过对象访问成员变量的格式
    //对象名.成员变量名
    s._nickname = "小八";
    
    //调用成员函数的格式
    //对象名.成员函数(参数表)
    s.printStudent();
    //姓名:xxx, 昵称 = 小八, 生日:1970年1月1日
    
    //2.通过引用访问对象的成员
    Student &sRef = s;
    //设置姓名
    sRef.setName("引用");
    sRef.printStudent();
    //姓名:引用, 昵称 = 小八, 生日:1970年1月1日
    
    //3.通过指针访问对象的成员
    Student *sPointer = &s;
    sPointer->setName("指针");
    sPointer->_nickname = "小针";
    sPointer->printStudent();
    //姓名:指针, 昵称 = 小针, 生日:1970年1月1日
}

类成员的可访问范围

访问范围说明符 含义 作用
public 公有的 使用它修饰的类的成员
可以在程序的任何地方被访问
private 私有的 使用它修饰的类的成员
仅能在本类内被访问
protected 受保护的 介于publicprivate之间,
使用它修饰的类的成员
能在本类内及子类中被访问

隐藏的作用

设置私有成员的机制叫做隐藏隐藏的一个目的就是强制对私有成员变量的访问一定要通过公有成员函数进行。这样做的好处是:如果以后修改了成员变量的类型等属性,只需要更改成员函数即可;否则,所有直接访问成员变量的语句都需要修改。

标识符的作用域与可见性

函数原型作用域

局部作用域

image.png

类作用域

类可以被看成是一组有名字的成员的集合,类X的成员m具有类作用域,对m的访问方式有如下3中:

  1. 如果在类X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以直接访问成员m。也就是说,m在这样的函数中起作用。
  2. 在类外,可以通过表达式x.m或者X::m来访问,其中x是类X的对象。这正是程序中访问对象成员的最基本方法。当然,这样的访问不能违反m的访问修饰符的限定。
  3. 在类外,可以通过ptr->m这样的表达式来访问,其中ptr为指向类X的一个对象的指针。当然,这样的访问不能违反m的访问修饰符的限定。

命名空间作用域

定义命名空间的一般形式如下:

namespace 命名空间名 {
    命名空间内的各种声明(函数声明、类圣经、...)
}

在命名空间内部可以直接引用当前命名空间中声明的标识符,如果需要引用其他命名空间的标识符,需要使用下面的方式:

命名空间名::标识符名

例如,定义一个命名空间如下:

namespace SomeNs {
    class SomeClass {.....};
    someFunc(int pram) {....};
}

int main() {
    //引用类名SomeClass或者函数名someFunc
    SomeNs::SomeClass obj1;
    SomeNs::someFunc(5);

    return 0;
}

在标识符前面总要加上这样的命名空间限定会显得过于冗长,为了解决这一问题,C++又提供了using语句,using与有两种形式:

using 命名空间名::标识符名;
或
using namespace 命名空间名;

作用域隐藏规则

具有命名空间作用域的变量也称为全局变量

对于在不同的作用域声明的标识符,可见性的一般原则如下:

上一篇 下一篇

猜你喜欢

热点阅读