Как сделать, чтобы два (или более) экземпляра класса typename класса использовали одну и ту же функцию

Мне интересно, возможно ли иметь класс, который использует template<typename T> с функциями, которые «typename T» использует по умолчанию. Я приведу примеры:

Заголовок:

includes all here
extern template class Object<rectangleBase>
extern template class Object(circleBase>

struct rectangleBase
{
int width, height;
int posX, posY;
};

struct circleBase
{
int radius;
int posX, posY;
};

template<typename T>
class Object {
public:
Object();
~Object();

void movePos(int x, int y);

void setPos(int x, int y);

T& returnObject() {
return object;
}
private:
T object;
};

Источник:

includes all here
template class Object<rectangleBase>
template class Object<circleBase>

Object<rectangleBase>::Object() {
rectangleBase* newObject;
newObject = new rectangleBase;
object = *newObject;
}

Object<circleBase>::Object() {
circleBase* newObject;
newObject = new circleBase;
object = *newObject;
}

void Object::movePos(int x, int y) { //here
object.posX += x;
object.posY += y;
}

void Object::setPos(int x, int y) { //here
object.posX = x;
object.posY = y;
}

С помощью функций setPos и ​​movePos возможно, что оба <rectangleBase> а также <circleBase> может использовать одну и ту же функцию вместо того, чтобы мне приходилось писать один и тот же код дважды, потому что они использовали бы один и тот же код, я покажу, где находятся функции в коде.

Если это невозможно, есть ли альтернатива?

0

Решение

Наличие одного и того же кода для нескольких разных типов данных (в общем, общее программирование) — это как раз то, для чего нужны шаблоны. Я думаю, что вы слишком обдумываете вещи. Для вашего варианта использования достаточно:

template<typename T>
class Object {
public:
Object()
: object()
{ }

void movePos(int x, int y) {
object.posX += x;
object.posY += y;
}

void setPos(int x, int y) {
object.posX = x;
object.posY = y;
}

T& returnObject() {
return object;
}
private:
T object;
};

Это все, что вам нужно. Это будет работать для любого T то есть конструируемый по умолчанию, а затем movePos а также setPos можно назвать, если T имеет эти две переменные-члены. Вам не нужно объявлять специализации вообще. Учитывая вышеизложенное, отлично работает следующее:

Object<rectangleBase> r;
r.setPos(5, 6);

Object<circleBase> c;
c.setPos(10, 20);
s.movePos(10, 10);
2

Другие решения

Я не уверен, в чем твоя проблема. Вы должны просто реализовать свои функции, создать экземпляр шаблона и использовать ваши объекты.

Я пытался, это работает. Пожалуйста, взгляните: http://ideone.com/717044

#include <stdio.h>

struct rectangleBase
{
int width, height;
int posX, posY;
};

struct circleBase
{
int radius;
int posX, posY;
};

template<typename T>
class Object {
public:

Object() { }
~Object() { }

void movePos(int x, int y)
{
object.posX += x;
object.posY += y;
}

void setPos(int x, int y)
{
object.posX = x;
object.posY = y;
}

T& returnObject() { return object; }

private:
T object;
};

int main(int argc, char ** argv)
{
Object<rectangleBase> a;
Object<circleBase> b;
b.setPos(1,2);
printf("px: %d", b.returnObject().posX);
}

Если вам интересно, сколько экземпляров компилятора функций будет сгенерировано,
(пример: код ваших функций огромен), скорее всего, компилятор сгенерирует столько экземпляров схожего кода, сколько у вас будет различных экземпляров. Оптимизатор может свернуть некоторые из них. Но если оптимизатор это сделает или нет — сказать сложно.

Подход, когда вы используете поля, методы, перечисления и т. Д. Типов параметров непосредственно из тела шаблона, вызывается с использованием зависимых типов. Да, такой подход затрудняет или делает невозможным создание экземпляра шаблона с типами, которые не имеют этого поля или функции-члена. Тем не менее, эта модель широко используется.

0

Да, ты можешь:

template <typename T>
void Object<T>::movePos(int x, int y) {
object.posX += x;
object.posY += y;
}

Даже ваши конструкторы могут использовать этот подход:

template <typename T>
Object<T>::Object() {
// This in fact does nothing really different than the default
// constructor of object but leaks one instance of T.
T* newObject;
newObject = new T;
object = *newObject;
}

Для шаблонов обычно требуется полная реализация в заголовочных файлах, но если вы хорошо работаете с ограниченными типами, которые приняты, вы можете явно создать экземпляры классов, а затем получить реализацию в исходном файле:

В заголовочном файле (в любом месте после определения класса):

extern template class Object<rectangleBase>;
extern template class Object<circleBase>;

В исходном файле (где угодно после определения методов):

template class Object<rectangleBase>;
template class Object<circleBase>;

Любой другой тип, чем rectangleBase или же circleBase не будет работать с этой настройкой.

0
По вопросам рекламы [email protected]