I have a base class, say BassClass, with some fields, which I made them protected, and some pure virtual functions. Then the derived class, say DerivedClass, like class DerivedClass : public BassClass. Shouldn't DerivedClass inherit the protected fields from BassClass? When I tried to compile the DerivedClass, the compiler complains that DerivedClass does NOT have any of those fields, what is wrong here?
thanks
If BassClass (sic) and DerivedClass are templates, and the BassClass member you want to access from DerivedClass isn't specified as a dependent name, it will not be visible.
E.g.
template <typename T> class BaseClass {
protected:
int value;
};
template <typename T> class DerivedClass : public BaseClass<T> {
public:
int get_value() {return value;} // ERROR: value is not a dependent name
};
To gain access you need to give more information. For example, you might fully specify the member's name:
int get_value() {return BaseClass<T>::value;}
Or you might make it explicit that you're referring to a class member:
int get_value() {return this->value;}
This works:
#include <iostream>
struct Base {
virtual void print () const = 0;
protected:
int val;
};
struct Derived : Base {
void print () { std::cout << "Bases's val: " << val << std::endl; }
};
Related
I have a class that inherits from a base class. The derived class has a template method. The base class has a specialized version of this method:
#include <iostream>
class Base {
public:
static void print(int i) { std::cout << "Base::print\n"; }
};
class Derived : public Base {
public:
static void print(bool b) { std::cout << "Derived::bool_print\n"; }
template <typename T>
static void print(T t) { std::cout << "Derived::print\n"; }
void Foo() {
print(1);
print(true);
print("foo");
}
};
int main()
{
Derived d;
d.Foo();
return 0;
}
The output is:
Derived::print
Derived::bool_print
Derived::print
The desired output is:
Base::print
Derived::bool_print
Derived::print
See code at https://onlinegdb.com/BY2znq8WV
Is there any way to tell Derived::Foo to use the specialization from Base instead of using the unspecialized version define in Derived?
Edit
The above example might be oversimplified as #Erdal Küçük showed. In actuality Derived subclasses from Base using CRTP, so it is not known if Base has a print method. A fuller example can be found at https://onlinegdb.com/N2IKgp0FY
This might help:
class Derived : public Base {
public:
using Base::print; //one of the many useful usages of the keyword 'using'
//...
};
See: Using-declaration in class definition
I know that it isn't possible to have class methods that are both pure virtual and static (see this discussion). So, I ask: is there a way to guarantee that a bunch of derived classes have static functions that do the same thing and that are guaranteed to be named in the same way?
Consider the following example:
#include <iostream>
#include <array>
// class base {
// public:
// virtual static constexpr size_t nums() = 0
// }
template<size_t num>
class derived1 {//: public base {
public:
static constexpr size_t nums() {return num;}
derived1() {}
};
template<size_t num>
class derived2 {// : public base {
public:
static constexpr size_t nums() {return num;}
derived2() {}
};
int main() {
std::cout << derived2<20>::nums() << "\n";
return 0;
}
I commented out the base class so that it compiles, but I want an interface class that guarantees a bunch of derived classes all have nums() named in the same way. In this particular example nums is named the same way in both derived class, but if I write a third derived class a few years from now, and I forget this convention, I don't want to be able to compile anything, ideally.
You could use CRTP as the base class, and then have a routine that depends on the derived class having implemented the expected static function.
Here's an example, and I have thunk_nums in the base class dependent on the derived class having nums, although they could have been named the same.
Note that if a function isn't used, it won't be generated, and so won't trigger an error. (Which may be desired behavior, or if not desired then steps would have to be taken to ensure it is generated.)
#include <iostream>
template <typename DERIVED>
class base {
public:
static constexpr size_t thunk_nums() {
return DERIVED::nums();
}
};
template<size_t num>
class derived1 : public base<derived1<num>> {
public:
static constexpr size_t nums() {return num;}
derived1() {}
};
template<size_t num>
class derived2 : public base<derived2<num>> {
public:
static constexpr size_t nums() {return num;}
derived2() {}
};
int main() {
std::cout << derived2<20>::thunk_nums() << "\n";
}
I try to initialize a static member of a CRTP base class. The base class holds a static template member of the derived class, while the derived class defines other data members. I want to statically initialize this variable. In code, a minimal example would be the following:
template<typename DERIVED>
class base {
public:
static DERIVED x;
};
class derived : public base<derived>
{
public:
int a;
};
int base<derived>::x {0};
int main()
{}
However, the above does not compile, but gives the error message error: specializing member 'base<derived>::x' requires 'template<>' syntax.
How can I get the static initialization to work?
The correct syntax is:
template <class T>
class base {
public:
static T x;
};
template <class T>
T base<T>::x{};
Note that you can't initialize x to a specific integer value, since then your base class won't compile when DERIVED is e.g. an std::string.
You probably also want your inheritance to be explicitly public or private. I.e.:
class derived : public base<derived> {
public:
int a;
};
Edit: To specialize x and it's initialization for specific types T, you have to specialize base itself. I.e.:
class A;
template <>
class base<A> {
public:
static int x;
};
// Note missing "template <>" here.
int base<A>::x{ 5 };
class A : public base<A> { };
This seems rather cumbersome, since you need to already forward declare A in this case before declaring the specialization. To me it feels you might want to rethink your design. Is this really required or is there a simpler way to accomplish what you want?
I have found the static initializer trick, which works in the above setting, too. It was described here and here. In the above context, it would be as follows:
#include <iostream>
template<typename DERIVED>
class base {
public:
static inline DERIVED x;
};
class derived : public base<derived>
{
public:
int a;
struct static_initializer {
static_initializer()
{
derived::x.a = 1;
}
};
static inline static_initializer static_initializer_;
};
int main()
{
std::cout << derived::x.a << "\n";
}
The above output the value 1.
Note: this works with C++17.
Can anyone let me know how to achieve:
the parameter of a method of a derived class being the parameter's
derived class (not the parameter's base class)?
This is what I want:
class Base{
public:
// Base class method has ParameterBase parameter
virtual void f(ParameterBase pb) = 0;
}
class Derived : public Base{
public:
// I want: Derived class method has ParameterDerived parameter;
void f(ParameterDerived pd){ //do something with pd; }
}
class ParameterBase{
// Base class of parameter;
}
class ParameterDerived : public ParameterBase{
// Derived class of parameter;
}
How to achieve above?
Do I have to use ParamterBase in the derived method's parameter list and dynamic_cast the parameter in the method body?
The feature you are asking for is called parameter type contra-variance. And C++ unfortunately, doesn't support it. C++ supports just the return type covariance. See here for a nice explanation.
Perhaps inconveniently, C++ does not permit us to write the function
marked hmm... above. C++’s classical OOP system supports “covariant
return types,” but it does not support “contravariant parameter
types.”
But you can use dynamic_cast<>() operator. But first, you must change the parameter type to pointer or reference, and add at least one virtual member (virtual destructor counts too) to your class ParameterBase to make compiler to create virtual method table for it. Here is the code with references. Pointers can be used instead.
class ParameterBase
{
public:
// To make compiler to create virtual method table.
virtual ~ParameterBase()
{}
};
class ParameterDerived : public ParameterBase
{
};
class Base
{
public:
// Pointers or references should be used here.
virtual void f(const ParameterBase& pb) = 0;
};
class Derived : public Base
{
public:
virtual void f(const ParameterBase& pb) override
{
// And here is the casting.
const ParameterDerived& pd=dynamic_cast<const ParameterDerived&>(pb);
}
};
int main()
{
Derived d;
ParameterDerived p;
d.f(p);
}
Supposing you want Derived to be called with ParameterDerived, but you also want to declare the interface in abstract base classes.
The interface MUST have the same parameter types, but you can still enforce the right parameter subclass with a dynamic_cast inside Derived::f
#include <iostream>
#include <string>
// interface
struct ParameterBase {
virtual ~ParameterBase() {};
};
struct Base {
virtual void f(ParameterBase *pb) = 0;
virtual ~Base() {};
};
// specific
struct ParameterDerived : public ParameterBase {
std::string name;
ParameterDerived(const std::string &name) : name(name) {}
ParameterDerived& operator=(const ParameterDerived& rhs) { name = rhs.name; }
~ParameterDerived() {};
};
struct Derived : public Base {
Derived(){}
Derived& operator=(const Derived &rhs) {}
virtual ~Derived(){}
void f(ParameterBase *pb) {
ParameterDerived *pd = dynamic_cast<ParameterDerived*>(pb);
if (pd) {
std::cout << "Derived object with derived parameter " << pd->name << std::endl;
} // else {throw std::exception("wrong parameter type");}
}
};
int main() {
Derived object;
ParameterDerived param("foo");
object.f(¶m);
}
SOLVED!
I want to create an array of different typed objects using templates.
Therefore I have a non-template class (Base), and a derived template class from Base class.
What I want to know is how can i access to derived class' generic value (T val)?
class Base{
public:
// a function returns T val, it will be implemented in Derived class
// EDIT : virtual function here
};
template<class T>
class Derived: public Base {
public:
T val;
Derived(T x) {
val = x;
}
// implementation.. it returns val
// EDIT : Implementation of virtual function
};
Solution: dynamic_cast, Note that Base class should have at least one virtual function.
Base *p[2];
p[0] = new Derived<int>(24);
p[1] = new Derived<double>(82.56);
int a = dynamic_cast<Derived<int>*>(p[0])->val; // casts p[0] to Derived<int>*
double b = dynamic_cast<Derived<double>*>(p[1])->val; // casts p[1] to Derived<double>*
cout << a << endl;
cout << b << endl;
Last time i checked, You cannot acess derived class members from a base class(non virtual).
You could modify your code this way since you are using templates.The type and value are passed to base class at construction and you can then use it.
template<typename T>
class Base {
T ini;
public:
Base(T arg){ini = arg;}
T ret(){return ini;}
};
template<class T>
class Derived: public Base<T> {
public:
T val;
Derived(T x) : Base<T>(x) {
//Base(x);
val = x;
}
// implementation.. it returns val
};
You can then instantiate it as usual and use it.
Derived<int> e(5);
e.ret();
It look like you want CRTP
The idea is to access the derived class members inside the base class. Note that you won't be able to contain an heterogeneous list of them.
template<typename D>
struct Base {
void doThings() {
// access the derived class getT function
auto var = static_cast<D&>(*this).getT();
cout << var << endl;
}
};
template<typename T>
struct Derived : Base<Derived> {
T getT() {
return myT;
}
private:
T myT;
};