Virtual functions cannot be constexpr however, when a function is implicitly virtual through inheritance, the compilers I have tried don't complain about it.
Here is a sample code:
class A
{
virtual void doSomething() {}
};
class B : public A
{
constexpr void doSomething() override {} // implicitly virtual constexpr
// but no compilation error
};
class C : public A
{
virtual constexpr void doSomething() override {} // explicitly virtual constexpr
// compilation error
};
I tried it with gcc 7.2.0 and clang 5.0.0.
Are those compilers not compliant to the standard in this regard, or are implicitly virtual constexpr functions allowed ?
The compilers have a bug. Note that this has been fixed in clang 3.5 already, not sure why you don't get an error, because I do.
The standard is pretty explicit about this in [dcl.constexpr]p3:
The definition of a constexpr function shall satisfy the following requirements:
it shall not be virtual;
[...]
It does't matter whether doSomething is implicitly virtual or not. In both cases, it is considered to be virtual, and so it violates the point above.
Related
I want to custom an Exception class, here's the code:
class TestException : std::exception{
public:
const char *what() const override {
return "TestException";
}
};
I used Clion and the IDE give me a warning on the function what():exception specification of overriding function is more lax than base version
But if I build the code with gcc, there's no warning came out.
I used c++ 14, gcc 6.5.0
Can anybody help to explain what does the warning mean and can I just ignore it?
what from std::exception is a virtual function and a virtual function in a derived class cannot have a laxer exception specification than the function it overrides in the base class.
This is mentioned in the section on "Exception specifications" in the standard.
18.4 Exception specifications [except.spec]
...
4. If a virtual function has a non-throwing exception specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall have a non-throwing exception specification, unless the overriding function is defined as deleted.
And the example given (which is somewhat similar to the code in the question) illustrates this as well.
struct B
{
virtual void f() noexcept;
virtual void g();
virtual void h() noexcept = delete;
};
struct D: B
{
void f(); // ill-formed
void g() noexcept; // OK
void h() = delete; // OK
};
The declaration of D::f is ill-formed because it has a potentially-throwing exception specification, whereas B::f has a non-throwing exception specification.
The solution is to change your code like:
class TestException : std::exception{
public:
const char *what() const noexcept override {
return "TestException";
}
};
See compilation here.
what member function of std::exception is declared as noexcept since C++11. You should therefore make your overridden what noexcept as well. (Actually, this is what the error message says.)
Note that the noexcept keyword must come before the override keyword (see, e.g., The order of override and noexcept in the standard for details).
The warning you are facing is related to the fact that you are using C++14, if you would compile with C++17 this becomes an error. Hence I would not recommend ignoring it.
Whats going on?
std::exception defines the method what as: virtual const char* what() const noexcept;. You inherit from this method and you re-implement it without specifying noexcept. By result, you are telling that your implementation can throw exceptions, while the base method indicates this should never throw. (And callers will assume so)
This was fixed in C++17, which made noexcept part of the type system, and requires you to fix this code:
const char *what() const noexcept override
override and final specifier has been introduced in C++11.The below program uses these specifier as follows:
#include<iostream>
template<typename T>
void display(const T& val) { std::cout<<val<<"\n"; }
class Shape {
public:
virtual ~Shape()= default;
virtual void Draw() { display("Shape::Draw()");}
virtual void DisplayName() { display("Shape");}
};
class Circle : public Shape {
public:
virtual ~Circle() = default;
virtual void Draw() override final { display("Circle::Draw()");}
virtual void DisplayName() override { display("Cicle");}
};
int main()
{
}
In the above sample program Circle::Draw() has been defined as override final specifier. This compiles successfully however if the same method is defined as final override, then it throws an compile time error.
Wanted to understand the use cases of override and final specifier for the same method for a class?. When we should use it in our program?
In my opinion it is a compiler bug. At least at www.ideone com the code is compiled successfully.
Acoording to the C++ Standard (10.3 Virtual functions)
4 If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function
D::f overrides B::f, the program is ill-formed.
[ Example:
struct B {
virtual void f() const final;
};
struct D : B {
void f() const; // error: D::f attempts to override final B::f
};
—end example ]
A class may not be a derived class of itself. So the code you showed shall be compiled.
Also
5 If a virtual function is marked with the virt-specifier override and
does not override a member function of a base class, the program is
ill-formed.
[ Example:
struct B {
virtual void f(int);
};
struct D : B {
virtual void f(long) override; // error: wrong signature overriding B::f
virtual void f(int) override; // OK
};
—end example ]
In your example function Draw of class Circle is marked with virt-specidier override and indeed overrides the function of the base class.
This is a compiler bug. According to the grammar that the C++11 standard is specifying in [class.mem]:
member-declarator: declarator
virt-specifier-seqopt pure-specifieropt
declarator
brace-or-equal-initializeropt
identifieropt
attribute-specifier-seqopt : constant-expression
virt-specifier-seq:
virt-specifier
virt-specifier-seq
virt-specifier virt-specifier:
override
final
The virt-specifier-seq doesn't imply any order in the virt-specifiers in the declaration.
When we should use it in our program?
This question might be worth looking at.
It looks like Vlad from Moscow is correct
From the override specifier at cppreference.com:
declarator virt-specifier-seq(optional) function-body
In both cases, virt-specifier-seq, if used, is either override or final, or final override or override final.
And again for the final specifier at cppreference.com:
declarator virt-specifier-seq(optional) function-body
virt-specifier-seq, if used, is either override or final, or final override or override final.
Compiler bugs aside, I would encourage you to pick an order and stick to it consistently - don't mix and match the word order through your codebase.
clang emits a warning when compiling the following code:
struct Base
{
virtual void * get(char* e);
// virtual void * get(char* e, int index);
};
struct Derived: public Base {
virtual void * get(char* e, int index);
};
The warning is:
warning: 'Derived::get' hides overloaded virtual function [-Woverloaded-virtual]
(the said warning needs to be enabled of course).
I don't understand why. Note that uncommenting the same declaration in Base shuts the warning up. My understanding is that since the two get() functions have different signatures, there can be no hiding.
Is clang right? Why?
Note this is on MacOS X, running a recent version of Xcode.
clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)
Update: same behavior with Xcode 4.6.3.
This warning is there to prevent accidental hiding of overloads when overriding is intended. Consider a slightly different example:
struct chart; // let's pretend this exists
struct Base
{
virtual void* get(char* e);
};
struct Derived: public Base {
virtual void* get(chart* e); // typo, we wanted to override the same function
};
As it is a warning, it doesn't necessarily mean it is a mistake, but it might indicate one. Usually such warnings have a means of shutting them off by being more explicit and letting the compiler know you did intend what you wrote. I believe in this case you can do the following:
struct Derived: public Base {
using Base::get; // tell the compiler we want both the get from Base and ours
virtual void * get(char* e, int index);
};
Another way of disabling the warning keeping the struct public interface intact would be:
struct Derived: public Base
{
virtual void * get(char* e, int index);
private:
using Base::get;
};
This disallows a consumer of Derived to call Derived::get(char* e) while silencing the warning:
Derived der;
der.get("", 0); //Allowed
der.get(""); //Compilation error
R. Martinho Fernandes solution's is perfectly valid if you actually want to bring the get() method taking a single char* argument into Derived scope.
Actually, in the snippet you provided, there is no need for virtual methods (since Base and Derived do not share any method with the same signature).
Assuming there is actually a need for polymorphism, the hiding behavior could nonetheless be what is intended.
In this case, it is possible to locally disable Clang's warning, with the following pragma :
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
// Member declaration raising the warning.
#pragma clang diagnostic pop
Warning means, that there will be no
void * get(char* e)
function in the scope of Derived class, cause it hidden by another method with same name.
Compiler won't search for function in base classes if derived class has at least one method with specified name, even if it has another arguments.
This sample code won't compile:
class A
{
public:
virtual void Foo() {}
};
class B : public A
{
public:
virtual void Foo(int a) {}
};
int main()
{
B b;
b.Foo();
return 0;
}
According to Wikipedia, in this example:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(float) override;
};
I thought override was not a C++ keyword, so what does it really mean?
We can achieve the same thing without that keyword so why would anyone need it?
There is also the keyword final which does not yet work on VS2010 :
struct Base1 final { };
struct Derived1 : Base1 { }; // ill-formed because the class Base1
// has been marked final
In C++11, override and final are "identifiers with special meaning". They are not keywords and only acquire special meaning if used in a specific context (when declaring virtual functions).
The idea is to enable to compiler to catch certain types of errors by allowing the programmer to explicitly state their intent (e.g. to override an existing virtual function rather than create a new one).
Here is the relevant quote from the standard, with examples:
C++11 10.3 4 If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function D::f
overrides B::f, the program is ill-formed. [ Example:
struct B {
virtual void f() const final;
};
struct D : B {
void f() const; // error: D::f attempts to override final B::f
};
—end example ]
5 If a virtual function is marked with the virt-specifier override
and does not override a member function of a base class, the program
is ill-formed. [ Example:
struct B {
virtual void f(int);
};
struct D : B {
void f(long) override; // error: wrong signature overriding B::f
void f(int) override; // OK
};
—end example ]
Consider:
struct device{
virtual void switchon() = 0 {}
};
int main()
{
}
I wrote code similar to following and it gave an error:
pure-specifier on function-definition
compilation terminated due to
-Wfatal-errors.
When I asked him, he showed me the following quote from the standard:
A virtual function declared in a class
shall be defined, or declared pure
(10.4) in that class, or both; but no
diagnostic is required (3.2).
I can't seem to understand what it means and I think this somehow is not relevant.
PS: If this is not the relevant quote, please guide me to the proper one so that I can have a better counterargument.
A pure virtual function may have a definition (out of class definition). That is completely optional. But what you are trying to do is plain wrong because
C++03 [Section 10.4/2] says:
[Note: a function declaration cannot provide both a pure-specifier and a definition —end note] [Example:
struct C {
virtual void f() = 0 { }; // Ill-formed
}
However you are free to write
struct device{
virtual void switchon() = 0;
};
void device::switchon() { } // Definition {optional}
int main()
{
}
You can have a "pure" virtual function, i.e. base class has no implementation of the function
virtual void switchon() = 0;
and optionally provide an implementation which derived classes must override.
void base_class::switchon() {}
OR
you can have a "non-pure" virtual function and provide a default or empty implementation
virtual void switchon() {}