简体   繁体   中英

Can I force a C++ class to be non-abstract?

In my C++ program, I have an abstract class named Foo and a class that inherits from it named Bar that's not supposed to be abstract. But I often add pure virtual methods to Foo and forget to override them in Bar , which makes Bar also an abstract class. So I often get code like this:

class Foo {
public:
    virtual void someMethod() = 0;
    //Other stuff
};

class Bar: public Foo {
    //Other stuff, but I forgot to override someMethod
};

int main(){
    Bar myVariable;    //Error here saying that Bar is abstract
    return 0;
}

Of course, this code doesn't compile, but it puts the error at the line Bar myVariable , saying that I can't instantiate an abstract class (since I forgot to override someMethod , Bar is abstract). But I think it would be more helpful if the compiler told me which method I forgot to override, since I have a lot of other things in both Foo and Bar and so to find what method I forgot to override, I would have to go through each pure virtual method in Foo and make sure it's overridden in Bar , which takes a lot of time.

So I would like to know if I can tell the compiler that Bar isn't supposed to be abstract, so that instead of putting the compiler error at the line where I declare a variable of type Bar saying that Bar is abstract (which isn't very helpful), it puts the compiler error at the declaration of Bar saying something like "You forgot to override someMethod ". Something like this:

nonabstract class Bar: public Foo { //Error here, Bar isn't supposed to be abstract but I didn't override someMethod
    //Some stuff
};

I did some research and found the final keyword, which applied to a class does so that the class can't be inherited. I tried marking Bar as final , thinking that there is no point in having an abstract class that can't be inherited, but in XCode all I got was a warning saying "Abstract class is marked 'final'" (but it still didn't tell me what method I forgot to override), and in Visual Studio it didn't change anything, it didn't even produce a warning. And even if it worked it wouldn't be perfect since I have nothing against having classes that inherit from Bar , I just don't want Bar to be abstract.

Is there a way I can tell the compiler that Bar isn't supposed to be abstract, so that it gives me an error when I forget to override a pure virtual method and tells me what method I forgot to override?

In some IDEs, notably Visual Studio, the "Errors" window only shows you the first line of each error. If you look at the compiler output, it'll show you additional information, if available; in this situation, that information would include what members were missing (and you can double-click on the line of output to go to the associated line of code). I'm not aware of any recent compiler which doesn't tell you which abstract functions were unimplemented.

Starting with C++17 you can use static_assert to ensure that a certain class is not abstract with std::is_abstract<T> :

static_assert(!std::is_abstract<Bar>(), "Bar must be non-abstract.");

This does not tell you which functions you forgot to override, but it lets you break the compile even in cases when Bar is not used. This could help in situations when Bar is part of a library that is compiled separately from the code that is using it.

I suppose you want to make sure that Bar is not abstract without the need of trying to instantiate it. For that purpose, you could use a static_assert with std::is_abstract :

class Bar: public Foo {
    //Other stuff, but I forgot to override someMethod
};
static_assert(!std::is_abstract<Bar>(), "Bar is ought to be not abstract.");

This will give you a compiler error at the static_assert ; if you implement someMethod (either in Bar or in Foo ), the compiler error will disappear.

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