This question already has answers here:
Can virtual functions be constexpr?
(3 answers)
Closed 1 year ago.
I'm implementing a pure virtual function in a C++ derived class, and mark the method final. I would also like to mark the function constexpr, but it appears the standard doesn't allow this.
Is there any practical reason why it would be difficult for compilers to implement this? Or is such a feature omitted due to the usual "this feature wasn't deemed to be important enough to add to the standard" thinking?
Based on the comments, it seems my original question didn't make it clear I am asking about constexpr final functions. The following code illustrates what I am trying to compile:
struct A {
virtual int foo() const;
};
struct B : public A {
// Note that this function is final, and is therefore no longer
// polymorphic in types derived from B (e.g., the function call
// no longer requires a lookup in the virtual method table
// when the compile-time type is known to be derived from B)
constexpr int foo() const final {
return 0;
}
};
Note that this was flagged as a duplicate of Can virtual functions be constexpr?, since in C++20, the above code would compile with or without the final keyword.
C++20 adds support for this code.
On godbolt, we can try it out: https://godbolt.org/z/f64e93dzY
It looks like this is Defect Report 647
Related
This question already has answers here:
When should I write the keyword 'inline' for a function/method?
(16 answers)
Closed 1 year ago.
I've been reading a c++ book, C++ Primer, and i was going through the class features and everything, and i encountered that, in a class most functions ( or every) are inline automatically.
What difference does it really make? explicitly defining an inline function vs implicitly defining an inline function, we could have already overloaded them inside the class scope anyways, i am finding it very difficult to understand this part. Is there any kind of performance gain by doing explicitly ?. in the photo we can see get() function using both methods explicit & implicit, can someone clarify me here.
I have to edit the question, because I've been told so many times that class members functions are not automatically inline. But the book c++ primer and other internet sources say that they are automatically inline.
Here is a piece of text from the book..
If a definition of a member function is within the class body it is implicitly inline. If you only declare it in the class body and you place the definition outside of it you need to make it explicitly inline.
This can be done in two ways:
struct test {
inline void foo();
};
void test::foo() {
}
Or
struct test {
void foo();
};
inline void test::foo() {
}
While both work, the second option is generally recommended.
This question already has answers here:
Access to protected member through member-pointer: is it a hack?
(4 answers)
Closed 4 years ago.
Consider
class A {
protected:
int m;
};
class B : public A {
void foo(A& a) {
a.m = 42; // ill-formed
}
void bar(A& a) {
auto pm = &B::m;
auto pm2 = static_cast<int A::*>(pm);
a.*pm2 = 42; // is this ok?
}
};
Trying to access A::m directly is ill-formed according to [class.protected]. However, it appears that we can always (?) circumvent this using static_cast, which allows a derived-to-base cast with pointers to members. Or is this somehow UB?
[Coliru link showing that bar compiles]
Yes, you can circumvent the protected mechanism in this way by using static_cast.
I think this is not undefined behavior in this particular case.
By using the static_cast you tell the compiler two things:
You ask the compiler to convert the B pointer into an A pointer.
You tell the compiler that this is ok to do so.
For 1. the compiler applies very limited checks of whether this is okay or not, and for static_cast it allows to cast from derived to base and the other way round, and that is it. So the compiler is happy. Whether a variable or pointer is protected or public is not part of the variable or pointer type. Neither pm nor pm2 carry the protected information.
For 2. the compiler completely leaves it up to you to make the decision whether this is okay or not in your design. It is not undefined behavior. It may still not be a good idea. pm2 is just a pointer to an int in A. You can reset it to a pointer to a different int in A which is public.
The background is that access control in C++ is generally per-class, plus there are some extra rules around protected which try to provide some level of access control on a per instance basis, but this protection is not perfect as you have demonstrated in your interesting question.
This question already has answers here:
Why is this constexpr static member function not seen as constexpr when called?
(2 answers)
Closed 5 years ago.
Consider this trivial test code:
class Test
{
public:
Test() {/* empty */}
private:
enum {BLAH = 42};
static constexpr int Magic() {return BLAH*4;}
float f[Magic()];
};
int main(int argc, char ** argv)
{
Test t;
return 0;
}
When I try to compile it (under MacOS/X using clang++ from the latest XCode), I get this compiler error:
Jeremys-Mac-Pro:~ jaf$ clang++ -std=c++11 ./test.cpp
./test.cpp:11:14: error: fields must have a constant size: 'variable length
array in structure' extension will never be supported
float f[Magic()];
Can anyone explain why this is an error? For comparison, if I move the Magic() method out of the Test class and make it a free-standing function, it compiles as expected, but I don't really want to do that because I want to keep Magic() and BLAH private to the Test class if possible.
(Note: I'm not trying to use variable-length arrays here; rather I'm trying to declare an array whose size is determined by the computation of a function at compile-time)
It's because functions within a class aren't processed until the class is complete. This rule allows a function defined within a class to access members of that class that are defined later in the class than that function. As a result, Magic() does not yet have a definition, so can't be evaluated at that moment of compile time.
This is correct behavior, though the error the various compilers generate are not helpful for understanding the problem.
The formal rules are in the C++ standard at [class.member]/6:
A class is considered a completely-defined object type (6.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have boiled down my issue to the following code all in a single *.cpp file:
class A {
public:
A() {};
int PerformAction() {
return Action();
}
protected:
virtual int Action();
}
class B: public A {
protected:
int Action();
}
int B::Action() {
return 4;
}
int main() {
B newB;
newB.PerformAction();
};
The previous code throws an Unresolved external symbol error on B::Action(). Changing a::Action()'s definition to:
virtual int Action() = 0;
yields instead the Cannot instantiate abstract class compiler error where it is used in the main function. All of the answers I have seen relate to having the code spread across multiple files, but this is occurring all within one source file. I imagine it is related to B's implementation of Action() being outside the class definition of B but can't see any reason why it should cause any error.
Your error messages, taken together, indicate a signature mismatch between A::Action and B::Action, such that B::Action does not become an overrider. The signatures must match perfectly (including cv-qualification of this), except that return type covariance is allowed.
And B::Action must be virtual. It will be implicitly if the signature matches, unless it is a template. Templates can't override.
If you have a C++11 compiler, I suggest using the override keyword, to make signature mismatch a compile error.
The previous code throws an Unresolved external symbol error on B::Action().
Indeed, all non-pure virtual functions must be defined, so that their address can be stored in the virtual function table for the class.
yields instead the Cannot instantiate abstract class compiler error
No it doesn't: http://ideone.com/IS7PJj
You'd get that error if you tried to directly instantiate A, or a subclass which didn't override the pure virtual function. B does override it, and so is not abstract.
Possibly, your real class B has an incorrect signature for Action, so it doesn't actually override the one declared in A. In C++11, you can add the override specifier to the one in B, to get a more helpful error message in that case.
I imagine it is related to B's implementation of Action() being outside the class definition of B
No, that shouldn't be an issue, as long as there's exactly one definition of the function.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ Overriding… overwriting?
What's the difference between override and overwrite? I've heard them used interchangeably but I suspect that's incorrect.
You can only overwrite what's been written and where it's been written, while you can override things elsewhere (for instance you can override members of base class in derived classes).
override is a C++11 keyword used to override base virtual method:
class A
{
virtual f(int) {}
};
class B
{
virtual f(int) override {} // override A::f(int)
};
This lets you make sure that A::F(int) gets overriden, meaning you are not creating new virtual function.
Of course this code won't compile if the function signature was different.
overwrite is not C++ keyword and it basically means to overwrite some file or text with new one.
The keyword override has been introduced because some times a programmer doesn't know whether he is overriding or whether he is creating a new virtual method with a different signature.
Using that keyword you either get an error or override virtual method.