c++ - Abgeleiteter Vorlagenklassenzugriff auf Basismitgliedsdaten




templates inheritance (2)

Hier ist die Basisklasse keine unabhängige Basisklasse (dh eine Klasse mit einem vollständigen Typ, die bestimmt werden kann, ohne die Argumente der Vorlage zu kennen), und _foo_arg ist ein nicht abhängiger Name. Standard-C ++ besagt, dass nicht abhängige Namen nicht in abhängigen Basisklassen nachgeschlagen werden.

Um den Code zu korrigieren, reicht es aus, den Namen _foo_arg abhängig zu machen, da abhängige Namen nur zum Zeitpunkt der Instanziierung gesucht werden können, und zu diesem Zeitpunkt ist die genaue _foo_arg , die untersucht werden muss. Beispielsweise:

// solution#1
std::cout << this->_foo_arg << std::endl;

Eine Alternative besteht darin, eine Abhängigkeit unter Verwendung eines qualifizierten Namens einzuführen:

// solution#2
std::cout << Foo<T>::_foo_arg << std::endl;

Bei dieser Lösung muss Vorsicht walten, denn wenn der nicht qualifizierte, nicht abhängige Name verwendet wird, um einen virtuellen Funktionsaufruf zu bilden, dann verhindert die Qualifikation den virtuellen Aufrufmechanismus und die Bedeutung des Programms ändert sich.

Und Sie können einen Namen aus einer abhängigen Basisklasse in der abgeleiteten Klasse einmal using :

// solution#3
template <class T>
class Bar : public Foo<T> {
public:
    ...
    void BarFunc ();
private:
    using Foo<T>::_foo_arg;
};

template <class T>
void Bar<T>::BarFunc () {
    std::cout << _foo_arg << std::endl;   // works
}

Diese Frage ist eine Förderung des in diesem Thread gestellten .

Verwenden Sie die folgenden Klassendefinitionen:

template <class T>
class Foo {

public:
    Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)
    {
        /* do something for foo */
    }
    T Foo_T;        // either a TypeA or a TypeB - TBD
    foo_arg_t _foo_arg;
};

template <class T>
class Bar : public Foo<T> {
public:
    Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
    : Foo<T>(bar_arg)   // base-class initializer
    {

        Foo<T>::Foo_T = T(a_arg);
    }

    Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
    : Foo<T>(bar_arg)
    {
        Foo<T>::Foo_T = T(b_arg);
    }

    void BarFunc ();

};

template <class T>
void Bar<T>::BarFunc () {
    std::cout << _foo_arg << std::endl;   // This doesn't work - compiler error is: error: ‘_foo_arg’ was not declared in this scope
    std::cout << Bar<T>::_foo_arg << std::endl;   // This works!
}

Beim Zugriff auf die Member der Basisklasse der Template-Klasse scheint es, als ob ich die Member immer explizit mit der Template-Stil-Syntax von Bar<T>::_foo_arg . Gibt es eine Möglichkeit, dies zu vermeiden? Kann eine 'using'-Anweisung / Direktive in einer Template-Klassenmethode zum Einsatz kommen, um den Code zu vereinfachen?

Bearbeiten:

Das Problem mit dem Gültigkeitsbereich wird gelöst, indem die Variable mit dieser Syntax qualifiziert wird.


Scheint, in Visual C ++ 2008 gut zu funktionieren. Ich habe einige Dummy-Definitionen für die Typen hinzugefügt, die Sie erwähnten, gab aber keine Quelle für. Der Rest ist genau wie du es ausdrückst. Dann eine Hauptfunktion, um zu erzwingen, dass BarFunc instanziiert und aufgerufen wird.

#include <iostream>

class streamable {};
std::ostream &operator<<(std::ostream &os, streamable &s) { return os; }

class foo_arg_t : public streamable {};
class a_arg_t : public streamable {};
class b_arg_t : public streamable  {};

template <class T>
class Foo {

public:
    Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)
    {
        /* do something for foo */
    }
    T Foo_T;        // either a TypeA or a TypeB - TBD
    foo_arg_t _foo_arg;
};

template <class T>
class Bar : public Foo<T> {
public:
    Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
    : Foo<T>(bar_arg)   // base-class initializer
    {

        Foo<T>::Foo_T = T(a_arg);
    }

    Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
    : Foo<T>(bar_arg)
    {
        Foo<T>::Foo_T = T(b_arg);
    }

    void BarFunc ();

};

template <class T>
void Bar<T>::BarFunc () {
    std::cout << _foo_arg << std::endl; 
    std::cout << Bar<T>::_foo_arg << std::endl;   
}

int main()
{
    Bar<a_arg_t> *b = new Bar<a_arg_t>(foo_arg_t(), a_arg_t());
    b->BarFunc();
}






name-lookup