In Java if you have a class like:
class Box<E>
{
some code
}
you can do the following using a wildcard:
Box<?> someBox;
someBox = new Box<Integer>();
someBox = new Box<Double>();
Is there a way to do this in C++?
In better words, how can I declare a variable in C++ that can hold either Box<Integer>
or Box<Double>
or Box<WhateverDataTypeHere>
?
template <typename T> class Box
should inherit from a non-template base (let's say class BasicBox
).
Then a pointer to BasicBox
can point to objects of the specializations of the derived template:
BasicBox *someBox = new Box<int>;
Or, since in modern C++™ manually managing memory should be avoided, using a smart pointer would be a better idea:
std::unique_ptr<BasicBox> someBox = std::make_unique<Box<int>>();
In addition to HolyBlackCat's excellent answer , I should also mention you do have a couple of other options to achieve a similar effect.
If you have some subset of classes, you can inherit them all from the same base like this:
class Base {
};
class Derived1 : public Base {
};
class Derived2 : public Base {
};
Then, you can create a Box
like this:
Box<std::uinque_ptr<Base>> genericBox;
genericBox
can now hold any derived, though because of the way C++ works, you probably need to hold it by pointer, reference, or std::unique_ptr
. Consequently, this is kind of messy, but works.
Also, I should mention that using this method will not work for types like int
or double
, so this is probably not useful if you need to use those types.
Better is, if you have access to it, to use std::variant
. This will allow you to store a specific set of types:
Box<std::variant<int, double>> genericBox;
This genericBox
can hold either a double
or an int
.
If you don't have direct access to std::variant
, there is also a boost::variant
which is basically the same thing. Or, if you have access to neither, you do have the option of a union
:
union GenericType {
int myInterger;
double myDouble;
};
Box<GenericType> genericBox;
Of course, std::variant
and boost::variant
is better, but this will work for you if you're ever in a situation where you don't have those.
Now, these options will only work if you ever know ahead of time what types you are attempting to store. If you don't know that, you have the option of std::any
:
Box<std::any> genericBox;
As with std::variant
, there is also a boost::any
. You can also implement it yourself if you really have to for some crazy reason. But I wouldn't recommend doing that unless you are doing it for educational purposes or something.
In C++ it's called templating
template <typename T>
class Box {
private:
T boxcontents;
}
replace T with whatever type you want. Here's some great documentation on the topic
Well, this is not something that someone want but you can use a pointer for basic types like int
For classes you can do that or use some base class for all types you may use.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.