I have two classes as follows in a header file
template<size_t N>
class Parent{
protected:
char array[N];
size_t i;
public:
virtual void operator()(int i);
};
template<size_t N>
void Parent<N>::operator()(int i){
this->i = i;
}
class Child: public Parent<16>{
public:
virtual void operator()();
};
Child has operator()() defined elsewhere in a cpp file. Whenever I include this header file from another cpp file I can access operator()() but operator()(int) is not even defined. Why is this? I thought since I inherit from a specific instance of Parent, all the methods of it should be instanced as well and available.
Apart from the errors in your code, this is an example of hiding: Your derived class declares a function of the same name but with different signature as a base class. Thus the base function is hidden:
class A { virtual void foo(); };
class B : public A { virtual void foo(int); /* hides A::foo() ! */ };
Inheritance only affects functions that have the same signature (with some mild exceptions).
Your base class function is declared as void Parent<N>::operator()(int), while in your derived class you declare void Child::operator()().
In C++11 you can explicitly say virtual void foo(int) override to trigger a compiler error if the function isn't overriding anything.
If you intentionally want to define a new function with the same name as an existing one but with different signature, and not overriding the base function, then you can make the base function visible with a using directive:
class C : public A
{
using A::foo();
void foo(int);
}; // now have both C::foo(int) and C::foo()
Because the Parent's operator() hides the Child's operator() (they have different signatures). How come you are not getting warnings when you compile your code?
This is how it should be :
class Child: public Parent<16>{
public:
using Parent<16>::operator();
virtual void operator()();
};
Related
It is very easy that we can make sure derived class must implement interface defined in base class.
That is pure virtual function.
For example:
class BaseClass
{
...
virtual void print()=0;
...
}
class DerivedClass :public BaseClass
{
// function must be implement, otherwise compiler will complain ...
void print()
{
}
};
Can we defined a static interface in base class and make sure the interface must be implement in derivate class?
I want something like this
class BaseClass
{
...
static void print(); // base class only define static interface
...
}
class DerivedClass :public BaseClass
{
// derived class must implement interface, otherwise compiler will complain ...
static void print()
{
}
};
I have no idea about this.
Thanks for your time.
It is not possible to make a virtual static function. For the simple reason that when calling a static function, you always know the class that defines that function in compile time. Unlike virtual functions, where you don't know the type of the object whose method you're calling.
For example:
class A
{
public:
virtual void f() {printf("A");}
};
class B : public A
{
virtual void f() override {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
In the above example, inside the function g, the correct function is invoked (B::f). Even though while compiling the function it is not known what the type of its argument is (it could be A or any class derived from A).
Without making f() virtual, you would have overloaded the method f, rather than overridden it. Which means that in the following example, the output would be "A", even though you might expect it to be "B":
class A
{
public:
void f() {printf("A");}
};
class B : public A
{
void f() {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
This may cause serious bugs, and it is suggested to never overload base class methods, and to always use the override keyword when overriding a virtual method to escape those bugs.
When making a static function, you can simply overload it, it would not create a compilation error. However, you probably never should overload it, because it may hide a bug that is very difficult to track (you are certain that B::f() is being called while actually A::f() is being called).
Furthermore, it is not possible to 'force' the derived class to implement a static interface, because there is no such thing as a static interface. Because you have no virtual static functions, you may not pass a reference or pointer to the interface that would implement this function.
Here is a sample code:
#include <memory>
class A {
public:
template <class T> void f(std::unique_ptr<T>, int) {}
private:
virtual void f(int) = 0;
};
class B: public A {
public:
using A::f;
private:
virtual void f(int) override {}
};
int main() {
std::unique_ptr<float> a;
B* b = new B;
b->f(std::move(a), 1);
return 0;
}
When I compile it with clang++, I get an error:
'f' is a private member of 'A'
using A::f;
^
How to make the template method f(std::unique_ptr<T>, int) visible from class B?
Note: if the virtual method A::f(int) is moved to a public section - everything works fine.
By giving it distinct name from the completely unrelated private virtual f.
Having an overloaded function where different overloads have different access control level neither works nor makes sense. You should only use the same name if the functions actually do the same (or comparable given the arguments) thing, but than it does not make sense to make one public and one private.
If you have a public wrapper over private virtual (which is common, see e.g. std::basic_streambuf), just add suitable prefix/suffix to one of them (std::basic_streambuf uses pub on the public, but it usually makes more sense to add priv, impl or _ to the private virtual.
You can not use using for this as using can not distinguish between the template and the virtual f. What does work is a simple forwarder:
class B: public A {
public:
template <class T> void f(std::unique_ptr<T> p, int i)
{
A::f<T>(std::move(p),i);
}
private:
virtual void f(int) override {}
};
I know that when you want to declare a polymorphic function you have to declare the base class function virtual.
class Base
{
public:
virtual void f();
};
My question is are you required to declare the inheriting class function as virtual, even if it's expected that Child behaves as if it were "sealed"?
class Child : public Base
{
public:
void f();
};
No, you don't need to re-declare the function virtual.
A virtual function in a base class will automatically declare all overriding functions as virtual:
struct A
{
void foo(); //not virtual
};
struct B : A
{
virtual void foo(); //virtual
}
struct C : B
{
void foo(); //virtual
}
Declaring f() as virtual in Child helps some one reading the definition of Child. It is useful as documentation.
Once the base class override is marked as virtual all other overrides are implicitly so. While you are not required to mark the function as virtual I tend to do so for documentation purposes.
As of the last part: even if it's expected that Child behaves as if it were "sealed"?, if you want to seal the class, you can actually do it in C++11 (this was not fully implementable in C++03 generically) by creating a seal class like so:
template <typename T>
class seal {
seal() {}
friend T;
};
And then inheriting your sealed class from it (CRTP):
class Child : public Base, virtual seal<Child> {
// ...
};
The trick is that because of the use of virtual inheritance, the most derived type in the hierarchy must call the virtual base constructor (int this case seal<Child>), but that constructor is private in the templated class, and only available to Child through the friend declaration.
In C++ you would have to either create a seal type for every class that you wanted to seal, or else use a generic approach that did not provide a perfect seal (it could be tampered with)
What does it mean to have a using inside a class definition?
class myClass {
public:
[...]
using anotherClass::method;
};
That declaration unhides a base class member. This is most often used to allow overloads of a member function. Example:
class Base {
public:
void method() const;
};
class Derived : public Base {
public:
void method(int n) const;
// Without the using, you would get compile errors on d.method();
using Base::method;
};
The case I've seen it:
class A
{
void foo(int);
void foo(float);
}
class B : public A
{
void foo(string);
}
B b;
b.foo(12); // won't work!
Because I have implemented a new foo function in B with a different signature it hides the foo functions from A. In order to override this behavior I would do:
class B : public A
{
void foo(string);
using A::foo;
}
Most often, syntax like this is used like so:
class derived : public base {
public:
[...]
using base::method;
};
The using declaration here unhides a member declaration from the parent class. This is sometimes necessary if another member declaration in derived may hide the member from base.
If anotherClass is a base class that contains a member function like
virtual void f();
and you decide to overload the function in the derived class like
virtual void f(int);
it "hides" f() in the base class. Calling f() through a pointer to the derived class for example, would result in an error, since the compiler does not "see" the version of f() taking no arguments from the base class anymore.
By writing
using Base::f;
you can bring the base classes function back into scope, thus enabling overload resolution as you might have expected it to work in the first place.
I have an abstract class with a pure virtual function f() and i want to create a class inherited from that class, and also override function f(). I seperated the header file and the cpp file.
I declared the function f(int) in the header file and the definition is in the cpp file. However, the compiler says the derived class is still abstract.
How can i fix it?
The functions f() and f(int) do not have the same signature, so the second would not provide an implementation for the first. The signatures of the PVF and the implementation must match exactly.
Are you declaring f(int) in your base class as pure virtual or f()?
Pure virtual functions can have definitions inside their base class. A pure virtual function simply says that the derived type must also specify their own implementations of the function f(int).
class Base
{
public:
virtual void f(int) = 0;
}
Base::f(int)
{
//some code
}
class Derived : public Base
{
public:
virtual void f(int)
{//Implementation is needed in Derived since f(int) is pure virtual
}
}
What about using C++ templates?
template<typename T>
class Basic{
public:
void f(T);
};
template<typename T>
Basic<T>::f(T t){
//Do something generic here
}
You can use template specialization if your function f needs to do something else when it's parameter is a specific type. I'll use string in this example.
template<>
class Basic<string>{
public:
void f(string);
};
template<>
Basic<string>::f(string t){
//Do your special thing with a string
}
Hope this helps!