连侯老师都会搞混淆的override和overload

本文详细探讨了C++中的函数重载(overload)与重写(override)的区别与规则。重载强调函数名相同但参数列表不同,而重写关注于子类如何修改父类的虚函数。在重写时,函数签名必须完全匹配,返回类型可以是父类类型的协变。同时,文章指出,使用`final`关键字可以防止子类进一步重写特定函数。
摘要由CSDN通过智能技术生成
ellipse
图1 overload VS. overrite

1.override

test_override_final.hpp

#pragma once

#include <iostream>
#include <string>

namespace test_override_final
{
    struct BaseA {int val_; };
    struct DerivedA : public BaseA {std::string name_;};

    struct BaseY
    {
        virtual BaseA* foo(){}
        virtual BaseA foo1(){}
        virtual DerivedA* foo2(){}
        virtual void foo3(DerivedA *){}
        virtual void foo4(BaseA*){}
        virtual int bar(){}
        virtual void bar1(int){}
        virtual void bar2(int){}
    };

    struct DerivedY : BaseY
    {
        virtual DerivedA* foo() override {}   // [RIGHT] can be override

        virtual void bar1(int) override final {} // [RIGHT] 是虚函数还是用final矛盾吗?不矛盾,那是因为DerivedY想重写BaseY中的bar1所以用virtual,但不想DerivedY的子类重写DerivedY中的bar1所以加上了final
        // virtual void bar1(int) final override {} //  final与override顺序无关

        // foo1无法override是因为虽然DerivedA*转为BaseA*是协变,但DerivedA转BaseA不是协变
        //virtual DerivedA foo1() override {}  //! 错误C2555“test_override_final::DerivedY::foo1”: 重写虚函数返回类型有差异,且不是来自“test_override_final::BaseY::foo1”的协变

        // foo2无法override的原因同:可以将子类变量地址赋给父类指针;不可以将父类变量地址赋给子类指针,即可以协变但不能逆变
        //virtual BaseA* foo2() override {}     //! 错误C2555“test_override_final::DerivedY::foo2”: 重写虚函数返回类型有差异,且不是来自“test_override_final::BaseY::foo2”的协变

        //virtual long bar() override{}       //! 错误C2555“test_override_final::DerivedY::bar”: 重写虚函数返回类型有差异,且不是来自“test_override_final::BaseY::bar”的协变

        // 下面三个无法进行override的原因是函数的入参没有满足“完全一致”,即使满足协变也不行,必须完全一致
        //virtual void foo3(BaseA *) override {}  //! 错误C3668“test_override_final::DerivedY::foo3”: 包含重写说明符“override”的方法没有重写任何基类方法
        //virtual void foo4(DerivedA*) override {} //! 错误C3668“test_override_final::DerivedY::foo4”: 包含重写说明符“override”的方法没有重写任何基类方法
        //virtual void bar2(long) override{}  //! 错误C3668“test_override_final::DerivedY::bar2”: 包含重写说明符“override”的方法没有重写任何基类方法
    };
        
    // 综上,关于重写,1.函数的入参,不管是基本类型还是类类型,必须完全一致,对于类类型满足协变也不行,必须”完全一致“
    //                 2.函数的返回值,如果是基本类型则必须完全一致,如果是类类型可以放宽到协变


    auto main() -> int
    {
        std::cout << "test_override_final......." << std::endl;

        return 0;
    }
}

main.cpp

#include "test_override_final.hpp"

int main()
{
    std::cout << __cplusplus << std::endl;
    test_override_final::main();
}

2.overload

test_overload.h

#ifndef TEST_OVERLOAD_H_
#define TEST_OVERLOAD_H_

namespace test_overload
{
	struct BaseA{};
	struct DerivedA : public BaseA{};
	
    int mysum(int a, int b);
	
	//float mysum(int a, int b); //! error C2556: “float test_overload::mysum(int,int)”: 重载函数与“int test_overload::mysum(int,int)”只是在返回类型上不同
	                             //! error C2371: “test_overload::mysum”: 重定义;不同的基类型 

    //BaseA mysum(int a, int b);  //! error C2556: “test_overload::BaseA test_overload::mysum(int,int)”: 重载函数与“int test_overload::mysum(int,int)”只是在返回类型上不同
	                              //! error C2371: “test_overload::mysum”: 重定义;不同的基类型

	int mysum(int a);
	
	float mysum(int a, float b);

    // 综上,函数重载:
	//       1.如果只有返回值不同则编译器会认为是相同的函数,会认为是重定义,因此重载函数返回值可以相同也可以不同;
	//       2.函数参数可以是类型不同  或/和  个数不同

    auto main() -> int;
}
#endif

test_overload.cpp

#include "test_overload.h"
#include <iostream>

int test_overload::mysum(int a, int b)
{
	std::cout << "calling mysum(int a, int b)" << std::endl;
    return a + b;
}

int test_overload::mysum(int a)
{
	std::cout << "calling mysum(int a)" << std::endl;

    return a + 1;
}

float test_overload::mysum(int a, float b)
{
	std::cout << "calling mysum(int a, float b)" << std::endl;
	
    return a + b;
}


auto test_overload::main() -> int
{
    std::cout << "testing overload..." << std::endl;

    std::cout << "mysum(" << 3 << "," << 5 << ")=" << mysum(3,5) << std::endl;
    std::cout << "mysum(" << 3 << ")=" << mysum(3) << std::endl;
    std::cout << "mysum(" << 3 << "," << 5.0f << ")=" << mysum(3,5.0f) << std::endl;

    std::cout << "overload test pass" << std::endl;
	std::cout << "------------------------------" << std::endl;

    return 0;
}

main.cpp

#include <iostream>
#include "test_overload.h"

auto main() -> int
{
	std::cout << mypow(2.5) << std::endl;
	
	test_final_override::main();
	
	test_overload::main();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值