Can you make a class method not inherited?

I have a base class of a geometric object, which I use on my own, but I also want to inherit the class into another, which is a kind of extended version of the object, since they share a lot of logic. The base object has several static creation methods (you cannot use new ones because of argument conflicts), I don’t want to inherit them. Is there any way to indicate that they are not inherited?

EDIT: enable example

struct Banana { float length; Banana() {} Banana(float length) { this->length = length; } static Banana CreateByHalfLength(float halfLength) { return Banana(halfLength * 2); } }; struct AdvancedBanana : Banana { float bendAmt; AdvancedBanana(float length, float bendAmt) { this->length = length; this->bendAmt = bendAmt; } }; 

I don't want AdvancedBanana :: CreateByHalfLength to exist as long as I want Banana :: CreateByHalfLength to exist and be accessible from outside the class.

+5
source share
4 answers

Try this redclare function as private in the child:

  #include <iostream> class Banana { public: float length; float getLenght(){ return length; } void setLenght(float value){ length = value; } Banana() {} Banana(float length) { this->length = length; } static Banana CreateByHalfLength(float halfLength) { return Banana(halfLength * 2); } }; class AdvancedBanana : public Banana { public: float bendAmt; AdvancedBanana(float length, float bendAmt) { this->length = length; this->bendAmt = bendAmt; } private: static AdvancedBanana CreateByHalfLength(float halfLength); }; int main() { // work Banana a(1); a.CreateByHalfLength(1); AdvancedBanana b(0,1); //will fail // b.CreateByHalfLength(1); }; 
+3
source

You can only do this with private inheritance for AdvancedBanana.

 #include <stdio.h> struct Banana { float length; Banana() {} Banana(float length) { this->length = length; } static Banana CreateByHalfLength(float halfLength) { return Banana(halfLength * 2); } }; struct AdvancedBanana : private Banana { float bendAmt; AdvancedBanana(float length, float bendAmt) { this->length = length; this->bendAmt = bendAmt; } }; int main() { Banana b; b.CreateByHalfLength(1); AdvancedBanana bb(1, 2); //bb.CreateByHalfLength(2); return 0; } 

AdvancedBanana :: CreateByHalfLength must exist if you want Banana :: CreateByHalfLength to exist and be accessible from outside the class. And also this is a bad decision.

On the other hand, I am invited to create two or more classes or take functions from Bananas, for your requirement. It will be something like this.

 #include <stdio.h> struct Banana { float length; Banana() {} Banana(float length) { this->length = length; } }; static Banana CreateByHalfLength(float halfLength) { return Banana(halfLength * 2); } struct AdvancedBanana : private Banana { float bendAmt; AdvancedBanana(float length, float bendAmt) { this->length = length; this->bendAmt = bendAmt; } }; int main() { Banana b = CreateByHalfLength(1); AdvancedBanana bb(1, 2); //bb.CreateByHalfLength(2); return 0; } 
+1
source

If you want to automatically restrict derived classes to overloading static Banana CreateByHalfLength(float halfLength); , then a very quick way is to encapsulate this function inside the virtual final method.

eg.

 struct Banana { ... // Create a namesake wrapper for the `static` function and make it final virtual Banana CreateByHalfLength(float halfLength) final { return CreateByHalfLengthImpl(halfLength); } static Banana CreateByHalfLengthImpl(float halfLength) { return Banana(halfLength * 2); } }; 

With this arrangement, now any derived class will not be able to create a similar function static or non- static .
Here is a demo .

The disadvantage of this approach is that you add function overheads from virtual , and are also called with an unused object.

+1
source

What you are saying is a bit vague, and an example will be helpful. In particular, since you are using the word static, and it is not clear what its context is.

You cannot stop a derived class from inheriting all methods of a base class. The best you can do is to make it non-member requiring a base object parameter. Then you will need to disconnect the object before the call, but you can still call it.

What you offer seems to violate the Liskov principle of substitution. This means that you have to rethink your design.

Also, instead of B inheriting from A., you may need the base class Q, from which both A and B are taken. [1]

[1] Q is a joke, some biblical scholars believe that there is some general unreasonable book that they call Q, from which every Gospel is copied.

Edit: Optional.

In this example, some things are clearer. Let me make some basic adjustments to your understanding of C ++. You said that you have several static creation methods due to argument conflicts. I think it’s better to say that overloading cannot solve various construction methods. The answer to this question is very simple: deploy overload in one of two ways. Use enumerations or use classes. The first thing you can see in streams calling read / add / read-write streams is by adding ios :: ate, etc.

In your case:

 enum BCT {halfLength,fullLength,quarterLength ...}; 

Then do static Banana Create (float size, type BCT = full length) {switch (type) {case fullLength: return Banana (size); case halfLength: Banana return (size * 2); case quarterLength: return Banana (size * 4); ...}}

an alternative version is to use classes to distinguish between parameter types (I believe that James Coplien named these instances)

 class FullLength class HalfLength class QuarterLength 

Then:

 static Banana Create(float length); // Full length static Banana Create(float halfLength, HalfLength &dummy); static Banana Create(float quarterlength, QuarterLength &dummy); 

New classes do not add anything to overhead, but eliminate overload ambiguity. I believe boost / std :: filesystem uses this path for its directorty iterators.

Having said that, as soon as you decide how to instantiate, they do not have to be static members. They can be ordinary constructors and this will solve your problem. Mostly. You still cannot stop AdvancedBanana from implementing the half-length method, but the encoder will know what it does.

A brief note on statics, static member functions are those that do not have access to this pointer or what some languages ​​call themselves, that is, they do not have access to the members of a particular instance. In fact, in preC ++ 98 days, before they had static, people did something like: ((Banana *)NULL)->static_function(arguments);

In your example, it is better to use constructors first. static constructors are best left to things like factories where they really are needed.

In addition, Mido's answer line: a.CreateByHalfLength(1); can compile or not compile, I use so many languages, sometimes I get confused about what is illegal :( but it shows bad thinking. The correct way to call static would be Banana :: CreateByHalfLength (1), which is not instance dependent.

-1
source

All Articles