在 C++您可以在子类中使用不同的参数值扩展参数化基类吗?

发布于 2024-08-17 02:12:12 字数 943 浏览 15 评论 0原文

在我理解的所有语言中,这是不可能的,但有人告诉我在 C++ 中这是可能的,但我很难相信它。本质上,当您参数化一个类时,您是在编译阶段创建一个唯一的类,不是吗?

如果我的问题不清楚,请告诉我。

这是我尝试解释我想要做的事情(注意类 L ):

//; g++ ModifingBaseClassParameter.cpp -o ModifingBaseClassParameter;ModifingBaseClassParameter

#include <iostream>

using namespace std;

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

template<typename T>
class F: Base<T>
{};

template<typename T>
class L: F<long>
{};

int main()
{
     Base<int> i;
     F<float> f;
     L<long> l;

     cout<<i.getMem()<<endl;
//     cout<<f.getMem()<<endl; // why doesn't this work
//     cout<<l.getMem()<<endl; // why doesn't this work
}

所以正如你所看到的(希望我的语法有意义)类 L 试图将其父级的 float 参数重新定义为 long 。这看起来当然不合法,但我不同意专家的观点。

In all the languages that I understand this is not possible but someone was telling me it was possible in C++ but I have a hard time believing it. Essentially when you parameterize a class you are creating a unique class in the compilation stage aren't you?

Let me know if I am not being clear with my question.

Here is my attempt at explaning what I am trying to do ( pay attention to class L ):

//; g++ ModifingBaseClassParameter.cpp -o ModifingBaseClassParameter;ModifingBaseClassParameter

#include <iostream>

using namespace std;

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

template<typename T>
class F: Base<T>
{};

template<typename T>
class L: F<long>
{};

int main()
{
     Base<int> i;
     F<float> f;
     L<long> l;

     cout<<i.getMem()<<endl;
//     cout<<f.getMem()<<endl; // why doesn't this work
//     cout<<l.getMem()<<endl; // why doesn't this work
}

So as you can see (hopefully my syntax makes sense) class L is trying to redefine its parent's float parameter to be a long. It certainly doesn't seem like this is legal but I will differ to the experts.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

唐婉 2024-08-24 02:12:12

如果您想问是否可以在 c++ 中执行此操作:

template <> 
class ParamClass<Type1> : public ParamClass<Type2> 
{
};

那么是的,这是可能的。

它经常被使用,例如定义模板列表或从其他类型继承特征。

If you mean to ask whether you can do this in c++ :

template <> 
class ParamClass<Type1> : public ParamClass<Type2> 
{
};

then yes, it is possible.

It is very often used, for example to define template lists or inherit traits from another type.

娇女薄笑 2024-08-24 02:12:12

您所要求的内容无法直接完成 - 但您可以通过使用默认模板参数来非常接近:

template <typename T>
class Base { };

template <typename T = int>
class X : Base<T> {};

class Y : Base<float>

class Z : X<long> {};

在这种特殊情况下,默认模板参数不会添加太多。即使为所有参数提供了默认值,您也必须提供模板参数列表来实例化模板。因此,在派生类中重写默认值通常仅对第二个及后续参数有用。

What you've asked for can't be done directly -- but you can come pretty close by using a default template parameter:

template <typename T>
class Base { };

template <typename T = int>
class X : Base<T> {};

class Y : Base<float>

class Z : X<long> {};

In this particular case, the default template parameter doesn't add much. You have to supply a template parameter list to instantiate a template, even if defaults are provided for all the parameters. As such, having a default that you override in a derived class is usually only useful for the second and subsequent parameters.

荒人说梦 2024-08-24 02:12:12
#include <iostream>
#include <typeinfo>

using namespace std;

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

template<typename T>
class F: public Base<T>
{};

template<typename T>
class L: public F<long>
{};

int main()
{
     Base<int> iNTEGER;
     F<float> fLOAT;
     L<long> lONG;

     int x;
     cout << typeid(iNTEGER.getMem()).name() << endl;
     cout << typeid(fLOAT.getMem()).name() <<endl; // this works now :)
     cout << typeid(lONG.getMem()).name() <<endl; // this works now :)
}

在 C++ 中继承默认是私有的,一旦公开,stephenmm 写的应该可以工作,除非你想问其他问题?

#include <iostream>
#include <typeinfo>

using namespace std;

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

template<typename T>
class F: public Base<T>
{};

template<typename T>
class L: public F<long>
{};

int main()
{
     Base<int> iNTEGER;
     F<float> fLOAT;
     L<long> lONG;

     int x;
     cout << typeid(iNTEGER.getMem()).name() << endl;
     cout << typeid(fLOAT.getMem()).name() <<endl; // this works now :)
     cout << typeid(lONG.getMem()).name() <<endl; // this works now :)
}

the inheritance is private by default in c++, once made public what stephenmm wrote should work unless you meant to ask something else ?

窝囊感情。 2024-08-24 02:12:12

您正在考虑模板吗?

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

class X: Base<int>
{};

class Y: Base<float>
{};

Are you taking about templates?

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

class X: Base<int>
{};

class Y: Base<float>
{};
伤痕我心 2024-08-24 02:12:12

您应该尝试编译它:

$ g++ so-test1.c++ -o so-test1.c++ && ./so-test
so-test1.c++:21: error: expected template-name before ‘<’ token
so-test1.c++:21: error: expected `{' before ‘<’ token
so-test1.c++:21: error: expected unqualified-id before ‘<’ token
so-test1.c++: In function ‘int main(int, const char**)’:
so-test1.c++:27: error: aggregate ‘Z z’ has incomplete type and cannot be defined

X 不是类模板,因此尝试在

class Z: X<long> {};

X 中实例化它没有任何意义,因为 X 没有要覆盖的模板参数。请记住,这

Base<int>

也不是类模板;它本身就是一个类,但是从模板完全实例化。您可以这样做:

....
template<typename T>
class X: Base<T> 
{};
...
class Z: X<long> 
{};

但是这里不会对覆盖任何模板参数产生混淆。

template<typename T>
class X: Base<int> 
{};
...
class Z: X<long>
{};

也可以,但是这里 X 中的模板参数未被使用,并且没有任何内容被覆盖。

华泰

You should try compiling it:

$ g++ so-test1.c++ -o so-test1.c++ && ./so-test
so-test1.c++:21: error: expected template-name before ‘<’ token
so-test1.c++:21: error: expected `{' before ‘<’ token
so-test1.c++:21: error: expected unqualified-id before ‘<’ token
so-test1.c++: In function ‘int main(int, const char**)’:
so-test1.c++:27: error: aggregate ‘Z z’ has incomplete type and cannot be defined

X is not a class template, so it makes no sense to try to instantiate it in

class Z: X<long> {};

X has no template parameters to override. Remember that

Base<int>

is not a class template either; it is a class in its own right, but fully instantiated from a template. You could do this:

....
template<typename T>
class X: Base<T> 
{};
...
class Z: X<long> 
{};

But here there is no confusion about overriding any template parameters.

template<typename T>
class X: Base<int> 
{};
...
class Z: X<long>
{};

works too, but here the template parameter in X is unused, and nothing is overridden.

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文