c++第八章-(虚方法与抽象方法)

1.虚方法(Virsual Method)

  • 虚方法是继承的,一旦在基类里把某个方法声明为虚方法,在子类里就不可能再把它声明为一个非虚方法了。
  • 在基类里把所有的方法都声明为虚方法会让最终生成的可执行代码的速度变得稍微慢一些,但好处是可以一劳永逸地确保程序的行为符合你的预期。
  • 析构器都是虚方法!从编译的角度看,他们只是普通的方法。如果他们不是虚方法,编译器就会根据他们在编译时的类型而调用那个在基类里定义的版本(构造器),那样往往会导致内存泄露!
class Pet
{
public:
    Pet(std::string theName);

    void eat();
    void sleep();
    virtual void play();//声明虚方法,解决子类在父类类型指针的情况下调用了父类的方法

protected:
    std::string name;
};

class Dog:public Pet
{
public:
    Dog(std::string theName);

    void bark();
    void play();
};

class Cat:public Pet
{
public:
    Cat(std::string theName);

    void climb();
    void play();
};

Pet::Pet(std::string theName)
{
    name = theName;
}

void Pet::eat()
{
    std::cout << name << "正在吃东西!\n";
}

void Pet::sleep()
{
    std::cout << name << "正在睡大觉!\n";
}

void Pet::play()
{
    std::cout << name << "正在玩儿!\n";
}

void Cat::climb()
{
    std::cout << name << "正在爬树!\n";
}

void Cat::play()
{
    Pet::play();
    std::cout << name << "玩毛线球!\n";
}

void Dog::bark()
{
    std::cout << name << "旺~旺~\n";
}

void Dog::play()
{
    Pet::play();
    std::cout << name << "正在追赶那只该死的猫!\n";
}

Cat::Cat(std::string theName):Pet(theName)
{

}

Dog::Dog(std::string theName):Pet(theName)
{

}

int main(int argc, const char * argv[])
{

    Pet *cat = new Cat("加菲");
    Pet *dog = new Dog("欧迪");

    //指针操作->
    cat -> sleep();
    cat -> eat();
    cat -> play();//因为指针的类型是Pet,所以实际是调用Pet::play()方法

    std::cout << std::endl;

    dog -> sleep();
    dog -> eat();
    dog -> play();//因为指针的类型是Pet,所以实际是调用Pet::play()方法

    delete cat;
    delete dog;

    return 0;
}

控制台返回的结果:

加菲正在睡大觉!
加菲正在吃东西!
加菲正在玩儿!
加菲玩毛线球!

欧迪正在睡大觉!
欧迪正在吃东西!
欧迪正在玩儿!
欧迪正在追赶那只该死的猫!

2.若没有声明虚方法的话,控制台返回的结果将会是:

加菲正在睡大觉!
加菲正在吃东西!
加菲正在玩儿!

欧迪正在睡大觉!
欧迪正在吃东西!
欧迪正在玩儿!

虚方法例子2

没有声明虚方法的时候

class animal
{
public:
    void sleep()
    {
        std::cout << "animal sleep " << std::endl;
    }
    void breathe()
    {
        std::cout << "animal breathe" << std::endl;
    }
};

class fish:public animal
{
public:
    void breathe()
    {
        std::cout << "fish bubble " << std::endl;
    }
};

int main(int argc, const char * argv[])
{
    fish fh;
    animal *pAn = &fh;

    pAn -> breathe();//是否声明成虚方法?????
    return 0;
}

控制台返回的内容:

animal breathe

相反声明成虚方法了,控制台返回的结果会是:

fish bubble 

2.所谓的多态,就是“一个接口,多种方法”。

  • 多态分2种。编译时多态,通过重载实现。运行时多态,通过虚函数实现。
  • 编译时的多态特点是运行速度快,运行时的特点是高度灵活和抽象。

3.抽象方法:抽象方法就是“纯虚方法”,其语法是“声明虚方法的同时,在其结尾加上”=0“。告诉编译器不用浪费时间在这个类里寻找这个方法的实现。

重载:overLoad
1.在同一个类中
2.函数名字相同
3.参数不同
4.virtual关键字可有可无
覆盖:overRide
1.位于派生类与基类
2.函数名字相同
3.参数相同
4.基类必须有virtual关键字

虚方法和抽象方法的区别:抽象方法不用实现。

  • 一般下类的析构函数里面都是释放内存资源,而基类的析构函数没有virtual声明的话,子类的析构函数将不会被调用,造成内存泄露。
  • 所以,析构器都是虚方法是为了当一个基类的指针删除一个派生类的对象时(delete XX),派生类的析构函数可以被正确调用。
  • 为了节省资源,只有当一个类被用来作为基类的时候,我们才把析构函数写成虚函数。
class ClxBase
{
public:
    ClxBase()
    {

    };

    virtual ~ClxBase()//基类析构器声明为虚函数的话,确保调用子类的析构器
    {

    };

    virtual void doSomething()
    {
        std::cout << "Do somehting in class ClxBase!\n";
    }
};

class ClxDerived:public ClxBase
{
public:
    ClxDerived()
    {

    };
    ~ClxDerived()
    {
        std::cout << "Output from the destructor of class ClxDerived!\n";
    };
    void doSomething()
    {
        std::cout << "Do something in class ClxDerived!\n";
    };
};
int main(int argc, const char * argv[])
{
    ClxBase *pTest = new ClxDerived;
    pTest -> doSomething();

    delete pTest;

    return 0;
}

c++第八章-(虚方法与抽象方法)

时间: 2024-12-12 13:58:21

c++第八章-(虚方法与抽象方法)的相关文章

C#类、接口、虚方法和抽象方法

虚方法和抽象方法都可以供派生类重写,它们之间有什么区别呢? 1. 虚方法必须有实现部分,并为派生类提供了重写该方法的选项.抽象方法没有提供实现部分,抽象方法是一种强制派生类重写的方法,否则派生类将不能被实例化 2. 抽象方法只能在抽象类中声明, 抽象方法必须在派生类中重写.虚方法不是也不必要重写.其实如果类包含抽象方法,那么该类也是抽象的,也必须声明为抽象的 3. 抽象方法必须在派生类中重写,这一点跟接口类似,虚拟方法不必.抽象方法不能声明方法体,而虚拟方法可以. 包含抽象方法的类不能实例化 ,

大龙的学习笔记之“虚方法,抽象方法,重写,抽象类,接口”

虚方法:可以重写,也可以不重写,英文名:virtual 抽象方法:必须重写,必须放在抽象类中,英文名:abstract 重写:可以重写三种方法:virtual,abstract,override,英文名:override 抽象类:可以有抽象方法,也可以有非抽象方法,英文名:abstract 接口:和抽象类相似,但是里面只有未实现的方法,英文名:interface 大龙的学习笔记之"虚方法,抽象方法,重写,抽象类,接口",布布扣,bubuko.com

虚方法与抽象方法有什么区别

抽象方法是只有定义.没有实际方法体的函数,它只能在抽象函数中出现,并且在子类中必须重写:虚方法则有自己的函数体,已经提供了函数实现,但是允许在子类中重写或覆盖. 重写的子类虚函数就是被覆盖了. 抽象方法 使用abstract关键字 public abstract bool Withdraw(-); 抽象方法是必须被派生类覆写的方法. 抽象方法是可以看成是没有实现体的虚方法 如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其它一般方法 虚方法 使用virtual关键字 public

虚方法和抽象方法的区别

虚方法:就是以virtual关键字修饰并在一个或多个派生类中实现的方法.如果一个方法被virtual标记,则不可再被static.abstract和override修饰. 抽象方法:是以abstract关键字修饰的方法,抽象方法可以看做是没有实现体的虚方法,并且必须在派生类中被重写,如果一个类包括抽象方法,则该类就是一个抽象类. (一) 虚方法 1.虚方法中必须包含实现,abstract修饰的方法一定不能包含实现: 2.virtual可以被子类重写,而abstract必须被子类重写: class

虚方法与抽象方法的区别

抽象方法 使用abstract关键字 public abstract bool Withdraw(…),没有方法体. 抽象方法必须被派生类重写. 任何类中,若存在抽象方法,这个类必须定义为抽象类(不过,里面可以不包含抽象方法). =============================================================================== 虚方法 使用virtual关键字 public virtual bool Withdraw(){....}(有

虚方法和抽象方法--基础回顾

抽象方法是只有定义.没有实际方法体的函数,它只能在抽象函数中出现,并且在子类中必须重写:虚方法则有自己的函数体,已经提供了函数实现,但是允许在子类中重写或覆盖.重写的子类虚函数就是被覆盖了. 抽象方法 使用abstract关键字 public abstract bool Withdraw(…); 抽象方法是必须被派生类覆写的方法. 抽象方法是可以看成是没有实现体的虚方法 如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其它一般方法 虚方法 使用virtual关键字 public v

虚方法与抽象方法

虚方法: 1.virtual方法表示此方法可以被重写, 也就是说这个方法具有多态.父类中的方法是通用方法,可以在子类中重写以重新规定方法逻辑. 2.virtual方法可以直接使用,和普通方法一样 3.不是必须重写的. 子类可以使用base.方法 的方式调用, 无论有没有在子类使用override去重写 virtual关键字只是明确标示此方法可以被重写, 其实它和一般的方法没有什么区别 相应的 sealed关键字标示此方法不可以被重写 虚方法和抽象方法的区别: 1.虚方法可以有实现体,抽象方法不能

C#虚方法和抽象方法区别

虚方法: 1.virtual方法表示此方法可以被重写, 也就是说这个方法具有多态.父类中的方法是通用方法,可以在子类中重写以重新规定方法逻辑.2.virtual方法可以直接使用,和普通方法一样.3.不是必须重写的. 子类可以使用base.方法 的方式调用, 无论有没有在子类使用override去重写.virtual关键字只是明确标示此方法可以被重写, 其实它和一般的方法没有什么区别相应的sealed关键字标示此方法不可以被重写 抽象方法: 1.抽象方法没有提供实现部分. 2.抽象方法只能在抽象类

C#中的虚方法和抽象方法(Thirteenth Day)

今天在云和学院学了很多,我这次只能先总结一下C#中的虚方法和抽象的运用. 理论: •用virtual修饰的方法叫做虚方法 •虚方法可以在子类中通过override关键字来重写 •常见的虚方法:ToString() Equals 实操: 定义一个People的父类,包括Name,Gender,Age,和一个PeoHi 的虚方法,定义两个子类Teacher,包括Year,Salary两个属性和一个PeoHi方法:子类Student,包括StadyNum和一个PeoHi方法. 定义子类Teacher(