简体   繁体   中英

Does C++ accept inline virtual function while performing polymorphism?

//header.h
#include<iostream>
using namespace std;
struct Base {
    virtual void vf();
};
struct Derived :Base {
    virtual void vf();
};
inline void Base::vf() {
    cout << "Base::vf()" << endl;
}
inline void Derived::vf() {
    cout << "Derived::vf()" << endl;
}

//source.cpp
#include"header.h"
int main() {
    Base *pb = new Derived;
    pb->vf();
}

//source2.cpp
#include"header.h"

It compiles and works in MSVC and g++.

But if I remove both inline keywords, a duplicate definition error will be caught by the linker since I include function definition twice, which will break the ODR.

Since I call the virtual function with a base pointer, it should be decided at run-time, and the compiler will ignore my inlining request, causing the duplicate error.

Do I get something wrong?

The One Definition Rule is mandatory. It is required by C++. A given object or a function must be defined exactly once. Removing the inline keyword (in your case) violates this rule, making the resulting program ill-formed.

Runtime polymorphism and virtual function dispatch happens at run time. You can only get to the run time part if your program is well-formed. If it breaks the ODR it is not well-formed, so how runtime polymorphism and virtual function dispatch works becomes a moot point. If your program is ill-formed there won't be anything to run and no base pointer at all.

It is true that an ODR violation does not require a diagnostic, but the resulting code is still broken. Please write a thank-you note to your compiler for alerting you to the problem.

As the code is currently written, the member functions are defined in header.h and marked inline . That's okay from the perspective of the language definition: inline means "it's okay to have multiple [identical] definitions of this function". From a maintenance perspective it can make things harder. In particular, when you do this, every time you change the implementation of any of those functions you have to recompile all of the source files that use that header. Putting the definitions of those functions into their own source file[s] means you only have to recompile the file[s] that changed.

If you don't want to mark your functions inline (and you don't want to define them inside the class definition, which makes them implicitly inline), then you have to put each function definition into exactly one source file. A useful first step is to define all of the non-inline member functions of a class in a single source file. So your source2.cpp might look like this (yes, that's member functions from two classes):

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

void Base::vf() {
    std::cout << "Base::vf()\n";
}

void Derived::vf() {
    std::cout << "Derived::vf()\n";
}

and you'd remove those definitions from header.h . So now header.h contains only the class definition; source2.cpp has the definitions of the member functions; and source.cpp has the main function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM