2010-08-31 4 views
1

Я хочу создать цепочку вызова как jquery-way в C++. Образец:Тип литья (из производного класса)

$('#obj').getParent().remove(); 

Итак, как я понимаю, каждый метод класса должен возвращать указатель на себя (это).

Все в порядке, пока я не вызову базовые методы. Код:

class Base 
{ 
    Base *base1() { return this; } 
    Base *base2() { return this; } 
}; 

class Derived : Base 
{ 
    Derived *derived1() { return this; } 
    Derived *derived2() { return this; } 
}; 

Derived *obj = new Derived(); 
obj->derived1()->derived2(); // Everything is okay 
obj->derived1()->base1()->derived2(); // Fail at second step 

Несомненно, base1 возвращает указатель для базы. Есть ли способ сделать автоматическое кастинг?


UPD: Может быть, это возможно с помощью макросов? Как

#define CORRECT_RETURN (this) 

и

Base::base1() { 
    return CORRECT_RETURN; 
} 

Что-то в этом пути. Или компилятор не будет смотреть на такую ​​конструкцию?

+0

Это совсем не так, как работает функция «jquery-way». Конечно, нет способа сделать то, что вы пытаетесь сделать. Функция, которую вы пытаетесь вызвать на Base (после вашего вызова base1()), должна, конечно, находиться в интерфейсе Base. –

+0

Я не уверен, чего вы пытаетесь достичь. Если он объединяет вызовы, вы можете сделать это, добавив бесконечное без использования наследования. Если цель состоит в том, чтобы создать правильно напечатанную копию, вам нужно будет изучить броски типа ковариации или перегрузки. – rerun

+0

Подпись «base()» означает, что вы получаете указатель на базу, что не имеет большого смысла. Имена методов должны быть изменены в соответствии с любой функцией, которую они обслуживают, вместо того, чтобы просто быть геттерами для этого «указателя». Если вы хотите «этот» указатель, просто пропустите геттеры. Вы все равно можете вернуть «это» из любой функции и использовать ковариацию (как предложил Тайлер). –

ответ

2

Да. Переопределите методы base1 и base2 в Derived, чтобы изменить их возвращаемое значение от Base* до Derived*, например.

class Derived : Base 
{ 
    Derived *base1() { return this; } 
    Derived *base2() { return this; } 
    Derived *derived1() { return this; } 
    Derived *derived2() { return this; } 
}; 

Это называется ковариационной типов возврата и является легальным в C++.

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

class Derived : Base 
{ 
    Derived *base1() { Base::base1(); return this; } 
    Derived *base2() { Base::base2(); return this; } 
    Derived *derived1() { return this; } 
    Derived *derived2() { return this; } 
}; 

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

+1

Не забудьте виртуальный на базе. Как определено, вы скрываетесь, поэтому вы не получите полиморфизм. –

+0

Виртуальные методы, вероятно, являются хорошей идеей с такой иерархией, но на самом деле для этого не требуются. 'obj' является' Derived * ', поэтому' obj-> производным1() 'является' Derived * ', поэтому' obj-> производный1() -> base1() 'вызывает' Derived :: base1' (который фактически возвращает 'Derived *') независимо от того, является ли 'base1' виртуальным. –

+0

@ tyler-mchenry хороший ответ. Не могли бы вы посмотреть на обновление, пожалуйста? – Ockonal

Смежные вопросы