В C++ действительно ли возможно передать, объявляют класс как наследовавшийся другому классу?

Я знаю, что могу сделать:

class Foo;

но могу я вперед объявлять класс как наследовавшийся от другого, как:

class Bar {};

class Foo: public Bar;

Вариант использования в качестве примера был бы ковариантными ссылочными типами возврата.

// somewhere.h
class RA {}
class RB : public RA {}

... и затем в другом заголовке, который не включает somewhere.h

// other.h
class RA;

class A {
 public:
  virtual RA* Foo();  // this only needs the forward deceleration
}

class RB : public RA; // invalid but...

class B {
 public:
  virtual RB* Foo();  // 
}

Единственная информация компилятор должна должна быть обработать объявление RB* B:Foo() это RB имеет RA как общедоступный базовый класс. Теперь ясно Вам был бы нужен somewhere.h, если Вы намереваетесь сделать какой-либо вид разыменования возвращаемых значений от Foo. Однако, если некоторые клиенты никогда не звонят Foo, затем нет никакой причины для них включать somewhere.h, который мог бы значительно ускорить компиляцию.

63
задан BCS 15 December 2011 в 17:03
поделиться

3 ответа

// wrap it in jQuery, now it's a collection
var $elements = $(someHTML);

// append to the DOM
$("#myDiv").append($elements);

// do stuff, using the initial reference
$elements.effects("highlight", {}, 2000);
-121--633589-

Передняя декларация действительно полезна для того, чтобы сообщить компилятору, что класс с таким именем существует и будет объявлен и определен и определен в другом месте. Вы не можете использовать его в любом случае, когда компилятор нуждается в контекстной информации о классе, а также ни одного использования для компилятора, чтобы рассказать это только немного о классе. (Как правило, вы можете использовать передовую декларацию только при обращении к этому классу без другого контекста, например, в качестве параметра или возвращаемого значения.)

Таким образом, вы не можете пересылать декларировать бар в любом сценарии, где вы тогда используете его, чтобы помочь Объявите Foo, и он не имеет смысла иметь передовую декларацию, которая включает в себя базовый класс - что это говорит вам, кроме того?

42
ответ дан 24 November 2019 в 16:24
поделиться

лучший способ, не позволить пользователям иметь слишком много привилегий. Предоставьте достаточно интерфейса, чтобы пользователи могли делать то, что они хотят. (как банкомат с кнопками только для различных опций, без ввода с клавиатуры). Конечно, если вам нужно, чтобы пользователь нажал на ввод, то предоставьте текстовое поле, а затем в бэкэнд, используйте Perl для обработки запроса (например, санирование и т.д.). Мотив позволить своим пользователям ввести регекс - это искать последовательность узоров верно? В этом случае самый простой и безопасный способ - это сказать им ввести только последовательность. Затем на заднем конце вы используете регекс Perl для его поиска. Есть ли еще какие-либо веские причины для того, чтобы пользователь вводил данные самостоятельно?

-121--2702183-

Я бы поместил это в комментарий, но не хватает места.

При написании пользовательского ограничения очень важно проверить параметр roityDirection и убедиться, что логика выполняется только в нужное время.

Этот параметр указывает, выполняется ли ограничение при обработке входящего запроса или выполняется при создании URL-адреса (например, при вызове Html.ActionLink ).

В вашем случае я думаю, что вы хотите поместить весь ваш соответствующий код в гигантский «if»:

public bool Match(HttpContextBase httpContext, Route route,
    string parameterName, RouteValueDictionary values,
    RouteDirection routeDirection) 
{
    if (routeDirection == RouteDirection.IncomingRequest) {
        // Only check the content type for incoming requests
        return httpContext.Request.ContentType == mimeType; 
    }
    else {
        // Always match when generating URLs
        return true;
    }
}
-121--3643164-

Форвардные объявления являются объявлениями, а не определениями. Таким образом, все, что требует объявления класса (как указатели на этот класс), нуждается только в прямом объявлении. Однако все, что требует определения, т.е. должно знать фактическую структуру класса, не будет работать только с форвардным объявлением.

Производные классы определенно должны знать структуру своего родителя, а не только то, что родитель существует, поэтому прямого объявления будет недостаточно.

40
ответ дан 24 November 2019 в 16:24
поделиться

Не думаю, что это полезно. Подумайте: вы определили класс Bar:

class Bar {
public:
    void frob();
};

Теперь вы объявляете класс Foo:

class Foo;

Все, что вы можете сделать с Foo, - это создать указатель на него. Теперь предположим, что вы добавили информацию о том, что Foo является производным от Bar :

class Foo: public Bar;

Что теперь вы можете делать, чего не могли делать раньше? Я думаю, что все, что вы можете сделать, это принять указатель на Foo и преобразовать его в указатель на Bar , а затем использовать этот указатель.

void frob(Foo* f) {
    Bar *b = (Bar)f;
    b->frob();
}

Однако вы должны были сгенерировать указатель в другом месте, поэтому вместо этого вы могли просто принять указатель на Bar .

void frob(Bar* b) {
    b->frob();
}
-1
ответ дан 24 November 2019 в 16:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: