Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Why can't a derived class add a const qualifier to a method?

+5
−0

Say we have an abstract class Foo declared as so:

class Foo {
  public:
    virtual void test() = 0;
};

Let's say that we make a derived concrete class FooDerived, and decide to mark it's version of test as const as it doesn't modify its state.

class FooDerived : public Foo {
  public:
    void test() const override { std::cout << "FooDerived!" << std::endl; }
};
main.cpp:12:10: error: ‘void FooDerived::test() const’ marked ‘override’, but does not override

Why is this not allowed? I thought that it would be, given that the only real function of the qualification is to be able to be called on const instances. It shouldn't be any more restrictive on the caller than the non-const version. Also, is there a good way to achieve this?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

2 answers

You are accessing this answer with a direct link, so it's being shown above all other answers regardless of its score. You can return to the normal view.

+4
−1

@InfiniteDissent‭ gives an excellent explanation why such a feature would be problematic from a programming language design perspective. As a consequence, C++ is defined such that the code you wanted to write is no valid C++ code and thus compilers will reject it.

Although not directly addressed by the technical nature of your question, I would like to add an aspect about semantic aspects of such overriding scenarios: You expected this feature to be supported because, from your position, adding constness in a derived method is just an additional guarantee to the caller, and thus it seems safe to add this guarantee when overriding.

But, not modifying the object may in some cases actually mean a violation of the base class interface contract: Assume the base class method is defined such that calling it will bring the object to a defined state (for example, re-initializing it). Then a client holding an object of the base class type will, when calling that method, assume that the object will be brought to that state. If the overriding function, however, will not touch the object, this can mean a breach of this contract.

I just mention this to make it clear that, also from an interface design point of view, adding constness for a derived method is not always "safe" but can result in a broken class hierarchy.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

1 comment thread

LSP (1 comment)
+7
−0

Because method constness is part of the type signature for the method, and const/non-const methods are completely separate as far as the language is concerned. When you override a method in a derived class, the type signature must match exactly, otherwise you are not overriding at all.

Consider that it is possible to have separate const and non-const methods on the same class, which can contain different code:

class Foo {
public:
    virtual void test() = 0;
    virtual void test() const = 0;
};
class FooDerived: public Foo {
public:
    void test() override { std::cout << "Non-const\n"; }
    void test() const override { std::cout << "Const\n"; }
}

If the language allowed you to add const to a derived method, there would now be ambiguity over which base class method the void test() const derived method was overriding — is it overriding the base class const method, or just adding const to the base class non-const method? If the language were to try to resolve this with a rule like "You can add const to an overridden method only if the base class doesn't also define a const method of the same name", you would create the possibility that adding a const method to the base class would actually change which method the derived class was overriding, which would be very surprising behaviour.

This is the same reason you can't override a method while changing the return type (e.g. from float to double). It may seem like a convenient and simple thing to do, but it violates the rule that an overriding method must match the type signature of the base method.

Also, is there a good way to achieve this?

It's not really clear what you want to achieve by changing the method constness, but here are some suggestions:

  • If you want the method to be const when called through the base class, add const to the signature on the base class.
  • If you want both const and non-const methods to be callable through the base class, you need to add both signatures to the base class and override them separately.
  • If you can't, or don't want to, change the base class, but just want to call the method on const instances of the derived class, you can add a separate const method to the derived class (which won't be an override). However, this method will only be callable if you have an actual FooDerived reference or pointer, rather than a reference to the base class.
History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »