I can't figure it out why the Derived class remains Abstract after overriding function fun().
Here is the error message:
error: invalid new-expression of abstract class type 'Derived' Base *t = new Derived(a);
error: no matching function for call to 'Base::fun(int&)'int i = t->fun(b);
#include <iostream>
using namespace std;
class Base
{
protected:
int s;
public:
Base(int i = 0) : s(i) {}
virtual ~Base() {}
virtual int fun() = 0;
};
class Derived: public Base
{
public:
Derived(int i) : Base(i) {}
~Derived() { cout << --s << " "; }
int fun(int x) { return s * x; }
};
class Wrapper
{
public:
void fun(int a, int b)
{
Base *t = new Derived(a);
int i = t->fun(b);
cout << i << " ";
delete t;
}
};
int main()
{
int i, j;
cin >> i >> j;
Wrapper w;
w.fun(i, j);
return 0;
}
The function has two different signatures between the base class and derived class
virtual int fun() = 0;
but then the derived class
int fun(int x) { return s * x; }
if you would add override it would alert you to this mistake
int fun(int x) override { return s * x; }
The problem is that
int fun(int x) { return s * x; }
does not override
virtual int fun() = 0;
because the argument list is different (no arguments vs. a single int). If you'd written
int fun(int x) override { return s * x; }
as you should since C++11, then the compiler would have given you an error about this.
Related
What is wrong with the following code?
struct A {
virtual int hash() const = 0;
virtual int hash(int x) const = 0;
};
struct B : public A {
int hash() const final {
return 10;
};
int hash(int x) const override {
return 10;
};
};
struct C : public B {
int hash(int x) const override {
return x;
}
};
#include <iostream>
int main() {
C a;
std::cout << a.hash() << std::endl;
std::cout << a.hash(20) << std::endl;
return 0;
}
I got compile error with the following error message
xx.cc:26:23: error: too few arguments to function call, single argument 'x' was
not specified
std::cout << a.hash() << std::endl;
~~~~~~ ^
xx.cc:17:3: note: 'hash' declared here
int hash(int x) const override {
^
1 error generated.
This is name hiding issue. According to the rule of name lookup,
(emphasis mine)
name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
So C::hash hides the name from the base class.
You can apply using to introduce the name into the class C scope.
struct C : public B {
using B::hash;
int hash(int x) const override {
return x;
}
};
Yeah, you have to redefine the overload within the derived class.
struct C : public B {
int hash(int x) const override {
return x;
}
int hash() const override {
return B::hash();
}
};
Or alternatively call via a reference to B
int main() {
C a;
B& b = a;
std::cout << b.hash() << std::endl;
std::cout << b.hash(20) << std::endl;
return 0;
}
I'll describe my question using the following sample code.
I have class B defined as follows:
class B
{
public:
inline B(){}
inline B(int(*f)(int)) :myfunc{ f }{}
void setfunction(int (*f)(int x)) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
int(*myfunc)(int);
};
I then define class A as follows:
class A
{
public:
A(int myint) :a{ myint }{ b.setfunction(g); }
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
To me the issue seems to be that the member function g has the signature int A::g(int) rather than int g(int).
Is there a standard way to make the above work? I guess this is quite a general setup, in that we have a class (class B) that contains some sort of member functions that perform some operations, and we have a class (class A) that needs to use a particular member function of class B -- so is it that my design is wrong, and if so whats the best way to express this idea?
You can use std::function:
class B
{
public:
inline B() {}
inline B(std::function<int(int)> f) : myfunc{ f } {}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
class A
{
public:
A(int myint) :a{ myint } {
b.setfunction([this](int a) {
return g(a);
}
);
}
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
You could generalize the class B. Instead of keeping a pointer (int(*)(int)), what you really want is any thing that I can call with an int and get back another int. C++11 introduced a type-erased function objection for exactly this reason: std::function<int(int)>:
class B
{
using F = std::function<int(int)>
public:
B(){}
B(F f) : myfunc(std::move(f)) { }
void setfunction(F f) { myfunc = std::move(f); }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
F myfunc;
};
And then you can just provide a general callable into B from A:
A(int myint)
: b([this](int a){ return g(a); })
, a{ myint }
{ }
Use std::function and std::bind
class B
{
public:
inline B(int(*f)(int)) :myfunc{ f }{}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
// ...
A a;
B b(std::bind(&A::g, &a));
Also note that you should initialize the function pointer to some default value (most likely null) and check for it when using, otherwise it's value is undefined.
You could use std::bind to bind the member function A::g.
class B
{
public:
inline B(){}
inline B(std::function<int(int)> f) :myfunc{ f }{}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
class A
{
public:
A(int myint) :a{ myint } {
b.setfunction(std::bind(&A::g, this, std::placeholders::_1));
}
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
Note you need to change the type of functor from function pointer to std::function, which is applicable with std::bind.
LIVE
I cannot understand why this does not compile:
#include<iostream>
#include<string>
using namespace std;
class Product {
public:
virtual void print() = 0;
virtual void slog() = 0;
virtual void loft() = 0;
};
class Bike: public Product {
private:
string s;
public:
Bike(string x){
s = x;
}
void print() {
std::cout << "Bike";
}
int slog() {
return 4;
}
string loft() {
return s;
}
};
int main() {
string s("Hello");
Product *p = new Bike(s);
p->print(); //works fine
cout << p->slog();//works fine
cout << p->loft(); //error
return 0;
}
The above code results in error. Why can't I override string class.
I want to call loft() using the pointer p.
Is there any way to achieve this using pointer object to abstract class Product
Firstly, you need to include string #include <string>.
There's no problem with loft method, you have a problem with print method. Child class has a return type of string and base class has a return type of void, thus you're not really overriding the function. Compiler sees the declaration of void print() in base class and you can't do a cout on that.
Here's your code with few fixes and comments on them, it should work fine.
#include <iostream>
#include <string>
using namespace std;
class Product {
public:
virtual void print() = 0;
virtual int slog() = 0;
virtual string loft() = 0;
//added virtual destructor so you can use pointer to base class for child classes correctly
virtual ~Product() {};
};
class Bike: public Product {
string s;
public:
Bike(string x) {
s = x;
}
void print() {
cout << "Bike";
}
int slog() {
return 4;
}
string loft() {
return s;
}
};
int main() {
string s("Hello");
Product *p = new Bike(s);
p->print();
cout << p->slog();
cout << p->loft();
return 0;
}
Also, please try to format your code better next time, it makes it easier to read
I want to create an adapter class in C++, but the interface that I want to adapt to has several non-virtual methods. Can I still use the regular adapter pattern?
#include <iostream>
using namespace std;
class NewInterface{
public:
int methodA(){ cout << "A\n"; }
virtual int methodB(){ cout << "B\n"; }
};
class OldInterface{
public:
int methodC(){ cout << "C\n"; }
int methodD(){ cout << "D\n"; }
};
class Old2NewAdapter: public NewInterface {
public:
Old2NewAdapter( OldInterface* a ){ adaptee = a; }
int methodA(){ return adaptee->methodC(); }
int methodB(){ return adaptee->methodD(); }
private:
OldInterface* adaptee;
};
int main( int argc, char** argv )
{
NewInterface* NI = new Old2NewAdapter( new OldInterface() );
NI->methodA();
NI->methodB();
return 0;
}
If I have this setup, the output will be "A D" instead of "C D" as it should.
So how can I adapt OldInterface to NewInterface, without rewriting NewInterface so that all methods are virtual?
Can you introduce another class? If you can then you can replace functions that use a NewInterface with an even NewerInterface:
class NewerInterface
{
public:
int methodA()
{
// preconditions
int const result = doMethodA();
// postconditions
return result;
}
int methodB()
{
// preconditions
int const result = doMethodB();
// postconditions
return result;
}
private:
virtual int doMethodA() = 0;
virtual int doMethodB() = 0;
};
class Old2NewerInterface : public NewerInterface
{
public:
explicit Old2NewerInterface(OldInterface& x) : old_(&x)
private:
virtual int doMethodA() { return old_->methodC(); }
virtual int doMethodB() { return old_->methodD(); }
private:
OldInterface* old_;
};
class New2NewerInterface : public NewerInterface
{
public:
explicit New2NewerInterface(NewInterface& x) : new_(&x)
private:
virtual int doMethodA() { return new_->methodA(); }
virtual int doMethodB() { return new_->methodB(); }
private:
NewInterface* new_;
};
why its not printing 'doub'? Looking for a detailed explanation. Thanks for your time!
#include<iostream.h>
using namespace std;
class B{
public:
virtual int ft(int i) { cout <<"int"; return 0;}
};
class D: public B {
public:
double ft(double i){cout << "doub"; return 0.0;}
int ft(int i) { cout <<"intdoub"; return 0;}
};
int main(){
B *pB = new D;
pB->ft(2.3);
}
o/p is 'intdoub'
The variable pB is of type B* and does not know about the function double D::ft(double), only virtual int B::ft(int). The conversion of the double value 2.3 to int happens automatically, although you should have gotten a compiler warning.
Try:
dynamic_cast<D*>(pB)->ft(2.3);
dynamic_cast<D*>(pB)->B::ft(2.3);