I don't think that you can instantiate a class with an abstract function, but I'm not sure.
No, you cannot.
Furthermore, I was also wondering if abstract functions can only have one implementation or multiple and if they can exist in non-abstract classes.
That's all of their purpuse. They can (silently) appear in a class hierarchy, with an abstract base and thus make derived classes abstract as well. But finally they must be implemented in a derived class that should be instantiatable.
I don't think that they can exist in non-abstract classes since an abstract functions means that a class is abstract and I believe that abstract functions can have multiple implementations.
A pure virtual function (no matter if inherited or directly declared) is what makes the class abstract.
As you mentioned contracts:
A pure virtual funciton can be considered as a contract, yes.
In c++ they are usually used to declare interfaces like follows
struct IMyInterface {
virtual void foo(int a, std::string b) = 0;
virtual int bar() = 0;
virtual ~IMyInterface() {}; // Note: Interfaces must have at least a
// virtual destructor function defined, but
// no other non pure virtual funcitons must
// be implemented.
};
A class can inherit multiple interfaces, which other classes can use as contracts, without the need to know the concrete class which implements it.
// A class implementing the interface
class Baz : public IMyInterface {
virtual void foo(int a, std::string b) {
// Do something with a and b
// ...
}
virtual int bar() {
return 3 * 5;
}
virtual ~Baz() = default; // Default destructors aren't automatically virtual!
};
// Another class implementing the interface
class Twiddle : public IMyInterface {
virtual void foo(int a, std::string b) {
// Do something with a and b
// ...
}
virtual int bar() {
return 42;
}
virtual ~Twiddle() = default;
};
// A class using the interface
class Client {
public:
// The concrete implementation can be configured by passing
// the interface in the vonstructor
Client(IMyInterface* intf_) : intf(intf_) {}
void someMethod() {
intf->foo(42,"Hello universe!");
int x = intf->bar();
}
private:
IMyInterface* intf;
};
Another way is, to use them in a Template Method design. I.e. an abstrct class, which has an algorithm or some behavior implemented, and relies on inheriting classes to implement an essential part of it.
class MyAbstractBase {
protected:
struct context {
int paramA;
std::string paramB;
};
int operateOnContext(const context& ctx) = 0;
public:
// Some behavior exposed to client classes
int doSomething() {
// Setup a context
context ctx { 42, "Hello universe!" };
return operateOnConetxt(ctx);
}
virtual ~MyAbstractBase() = default;
};
// An inherited class, which will write the context to a file
class Derived1 : public MyAbstractBase {
protected:
int operateOnContext(const MyAbstractBase::context& ctx) {
std::ofstream out("AFile.txt");
out << "Param A is:" << ctx.paramA << std::endl;
out << "Param B is:" << ctx.paramB << std::endl;
}
public:
virtual ~Derived1() = default;
};
// Another inherited class, which will send the context over a network connection
class Derived2 : public MyAbstractBase {
protected:
int operateOnContext(const MyAbstractBase::context& ctx) {
NetworkConn conn;
conn.connect("NetworkEndpoint");
conn.send(ctx.paramA);
conn.send(ctx.paramB);
conn.disconnect();
}
public:
virtual ~Derived2() = default;
};