Why C++ compiler gives this error? Why i can access lol() from B, but can not access rofl() [without parameters]. Where is the catch?
class A
{
public:
void lol(void) {}
void rofl(void) { return rofl(0);}
virtual void rofl(int x) {}
};
class B : public A
{
public:
virtual void rofl(int x) {}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.lol();
a.rofl(1);
a.rofl();
B b;
b.lol();
b.rofl(1);
b.rofl(); //ERROR -> B::rofl function does not take 0 arguments
return 0;
}
The B::rofl(int) 'hides' the A::rofl(). In order to have A's rofl overloads, you should declare B to be using A::rofl;.
class B : public A {
public:
using A::rofl;
...
};
This is a wise move of C++: it warns you that you probably also need to override the A::rofl() method in B. Either you do that, or you explicitly declare that you use A's other overloads.
Related
I have a class C that inherits both from Ai and B. A and B are unrelated. This is all best explained with the code below. In main(), I have a variable a defined as std::unique_ptr<A>, but initialized with C. I cannot change this definition.
My question is, given a defined like this, how can I call functions defined in B or C or Ai correctly?
#include <memory>
class A
{
public:
void fun_a() {}
};
class B
{
public:
void fun_b() {}
};
class Ai : public A
{
public:
void fun_ai() {}
};
class C: public Ai, public B
{
public:
void fun_c() {}
};
int main()
{
// I cannot change the following definition:
std::unique_ptr<A> a = std::make_unique<C>();
a->fun_a();
//a->fun_b(); // How ?
//a->fun_c(); // How ?
//a->fun_ai(); // How ?
return 0;
}
You can static_cast to C*:
static_cast<C*>(a.get())->fun_b();
static_cast<C*>(a.get())->fun_c();
static_cast<C*>(a.get())->fun_ai();
or you could make it polymorphic:
class A {
public:
virtual ~A() = default;
void fun_a() { std::cout << "fun_a\n"; }
};
and then dynamic_cast:
dynamic_cast<B*>(a.get())->fun_b();
dynamic_cast<C*>(a.get())->fun_c();
dynamic_cast<Ai*>(a.get())->fun_ai();
Note: dynamic_casts to pointer types may fail and return nullptr so, if there's any doubt, check the return value.
Demo
I ran into the following problem and I don't really know what the best way is to approach this. I want to evaluate expression objects that are constructed with a foo object. The expression class and its derived classes should be allowed to access private members of foo; but except from declaring all derived classes individually as friend I don't know how I could make this work - can I declare a virtual function a friend of foo?
class foo{
public:
foo(int a, int b, int c) : a(a), b(b), c(c) {}
void addExpression(expression *e){exp.push_back(e);}
bool evaluateAll(){
for(expression* e : exp){
if(!e->evaluate())
return false;
}
return true;
}
private:
int a,b,c;
std::list<expression*> exp;
};
The expression classes:
struct expression{
expression(foo *f) : f(f) {}
virtual bool evaluate() = 0;
private:
foo *f;
};
struct anExpression : public expression{
anExpression(foo *f) : expression(f) {}
bool evaluate(){
return f->a < f->b;
}
};
struct anotherExpression : public expression{
anotherExpression(foo *f) : expression(f) {}
bool evaluate(){
return f->a > f->b && f->a != f->c;
}
};
The mainfunction:
int main(int argc, char *argv[]){
foo f(3,2,1);
f.addExpression(new anExpression(&f));
f.addExpression(new anotherExpression(&f));
f.evaluateAll();
return 0;
}
This code doesn't work of course but I really don't want to add every derived class of expression as a friend or make expression inherit from foo. Is there another solution?
I would make expression a friend class of foo, that is, add the following to foo:
friend struct expression;
And then implement get-functions in expression, like so:
struct expression {
// other stuff
protected:
int get_a(foo const * f) { return f->a; }
}
The get-functions should be marked protected to reduce exposure. The parameter of the get-function is const, for good measure.
I may be wrong but isn't this a case for the Curiously recurring template pattern? https://en.m.wikipedia.org/wiki/Curiously_recurring_template_pattern
This question already has answers here:
Inherit interfaces which share a method name
(5 answers)
Closed 10 years ago.
Have code as below
// A has a virtual function F().
class A
{
public:
virtual void F() {};
};
// The same for B.
class B
{
public:
virtual void F() {};
};
// C inherits A and B.
class C : public A, public B
{
public:
// How to implement the 2 virtual functions with the same name but from
// different base classes.
virtual F() {...}
};
Note that there is a default implementation of F() in the base classes.
Thanks to Jan Herrmann and Spook. Is the below a simpler solution if we have to use some extra helpers?
#include <iostream>
// A has a virtual function F().
class A
{
private:
virtual void A_F() {}
public:
void F() {return A_F();};
};
// The same for B.
class B
{
private:
virtual void B_F() {}
public:
void F() {return B_F();};
};
// C inherits A and B.
class C : public A, public B
{
private:
virtual void A_F() {std::cout << "for A\n";}
virtual void B_F() {std::cout << "for B\n";}
};
int main()
{
C c;
c.A::F();
c.B::F();
return 0;
}
class C_a
: public A
{
virtual void F_A() = 0;
virtual void F() { this->F_A() };
};
class C_b
: public B
{
virtual void F_B() = 0;
virtual void F() { this->F_B() };
};
class C
: public C_a
, public C_b
{
void F_A() { ... }
void F_B() { ... }
};
If I'm remembing right the ISO committee thought about this problem and discussed a change of the language. But then ... somebody found this nice way to solve this problem :-)
Your second solution is better in case your are able to change your class hierarchy. You may have a lock at http://www.gotw.ca/publications/mill18.htm for a description why it is better.
Try this:
#include <cstdio>
class A
{
public:
virtual void F() = 0;
};
class B
{
public:
virtual void F() = 0;
};
class C : public A, public B
{
void A::F()
{
printf("A::F called!\n");
}
void B::F()
{
printf("B::F called!\n");
}
};
int main(int argc, char * argv[])
{
C c;
((A*)(&c))->F();
((B*)(&c))->F();
getchar();
return 0;
}
Take into consideration though, that you won't be able to call F from C's instance (ambiguous call).
Also, F has to be abstract in A and B, otherwise you'll get compilation error:
Error 1 error C3240: 'F' : must be a non-overloaded abstract member function of 'A'
Is there a nice way to call A::foo() from B::bar() in the following sample?
class A {
protected:
void foo() {}
};
class B : public A {
public:
void bar(A& a) { // edit: called with &a != this
a.foo(); // does not work
}
};
I can't think of anything other than declaring B to be a friend of A, but that could get pretty ugly with some more classes.
Any ideas?
Yes, you can use a base-class function.
class A {
protected:
void foo() {}
void do_other_foo(A& ref) {
ref.foo();
}
};
class B : public A {
public:
void bar(A& a) { // edit: called with &a != this
this->do_other_foo(a);
}
};
Why are you passing object of type A? You could do like this :
class B : public A {
public:
void bar() {
foo();
}
};
or, like this
class B : public A {
public:
void bar() {
A::foo();
}
};
Here's an approach to giving "protected" like access, allowing calls by any derived classes or object.
It uses a protected token type, required to un-lock privileged methods:
struct A
{
protected:
//Zero sized struct which allows only derived classes to call privileged methods
struct DerivedOnlyAccessToken{};
public: //public in the normal sense :
void foo() {}
public: //For derived types only :
void privilegedStuff( DerivedOnlyAccessToken aKey );
};
struct B: A
{
void doPrivelegedStuff( A& a )
{
//Can create a token here
a.privilegedStuff( DerivedOnlyAccessToken() );
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.foo();
a.privilegedStuff( A::DerivedOnlyAccessToken() ); // compile error.
B b;
b.doPrivelegedStuff( a );
return 0;
}
This is not my idea. I read it some place. Sorry I dont recall who's cunning idea it was.
I expect the compiler can elide the aKey parameter.
I have a class as follows:
Class A
{
virtual int doSomethingCool() = 0;
};
Class B : public A
{
int doSomethingCool();
};
Now the problem likes , I have a set of classes whcih are dependent on A as interface. I need to change the prototype of the function for one of the derived classes. i.e. i need to pass it a parameter.
Class C: public A
{
int doSomethingCool(int param);
};
Any suggestions how i can achieve this ?
No, you don't need to add it to the base class.
class A
{
public:
virtual int doSomethingCool() = 0 {}
};
class B : public A
{
public:
int doSomethingCool() {return 0;}
};
class C: public A
{
private:
int doSomethingCool(); // hide base class version!
public:
int doSomethingCool(int param) {return param;}
};
You can still call doSomethingCool() if done through a base class pointer:
C c;
//c.doSomethingCool (); // doesn't work, can't access private member
c.doSomethingCool (42);
A &a = c;
a.doSomethingCool ();
//a.doSomethingCool (42); // doesn't work, no member of A has that signature
Add it to the interface and default it to call the existing method. You don't have to do the default but don't make it pure otherwise all derived classes will have to implement. It might be better to leave it undefined or to throw. Depends on what you want to achieve.
class A
{
public:
virtual int doSomethingCool() = 0;
virtual int doSomethingCool(int param) {doSomethingCool()};
};
Make the function doSomethingCool() take the int parameter in A.
class A
{
public:
virtual void doSomethingCool(int param) = 0;
};
There's no problem. You can do it. The only caveat is that it will not be treated as an override of the base class virtual function.
class A
{
public:
virtual void doSomethingCool() = 0;
};
class B : public A
{
public:
void doSomethingCool();
};
class C: Public A
{
public:
void doSomethingCool(int param);
};
int main(){}
So while technically possible, you may really want to relook at the design of your interface class A.
One option may be to provide a default argument to A::doSomethingCool
virtual void doSomethingCool(int = 0) = 0;
This isn't syntactically correct C++.
No you can't change a prototype. How would it be used? What would be the value of the param if the non-parametric version would be called?
I would have introduced another, more specific, interface:
struct A
{
virtual int doSomethingCool() = 0;
};
struct A_specific : A
{
virtual int doSomethingCoolWithThis(int i) = 0;
};
class ConcreteA : public A
{
int doSomethingCool() { return 0; }
};
class ConcreteA_specific : public A_specific
{
int doSomethingCool() { return 0; }
int doSomethingCoolWithThis(int param) { return param; }
};
Then I would program to the correct interface:
int main()
{
const A& a1 = ConcreteA();
const A_specific& a2 = ConcreteA_specific();
a1.doSomethingCool();
a2.doSomethingCool();
a2.doSomethingCoolWithThis(2);
}
Just to give you another idea ;-)
Good luck!