gpt4 book ai didi

c++ - 使用模板函数传递模板参数时出错

转载 作者:太空宇宙 更新时间:2023-11-04 12:48:37 29 4
gpt4 key购买 nike

我在使用模板成员函数和模板变量时遇到问题。目标是为接口(interface)创建一个模板,该接口(interface)可以被继承并链接到一个或多个在运行时初始化的服务。该接口(interface)还将数据传递给这些专门的服务(例如 MyService)。举一个更简单的例子,使用这段代码:

#include <string>

class Interface
{
public:
template <class T> bool init(T *_Service) {AttachService(*_Service);} //This function does other stuff too.
template <typename T> void AttachService(T _Service) { m_AttachedService<T> = *_Service; }
template <typename T> T AttachedService() { return m_AttachedService; }
protected:
template<typename T> static T m_AttachedService;

class InterfaceListener
{
void Received()
{
int a = 1;
std::string b = "hello";
AttachedService().setA(a);
m_AttachedService.setB(b);
};
};
};

class Service
{
Service();
~Service();
virtual void init() = 0;
};

class MyService : public Service, public Interface
{
MyService();
~MyService();
private:
int A;
std::string B;
protected:
Interface x;
public:
void init() { x.init(this);}
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};

int main();
{
MyService myserv;
myserv.init();
}

我收到以下错误:

C2672: 'Interface::AttachedService': no matching overloaded function found
C2783: 'T Interface::AttachedService(void)': could not deduce template argument for 'T'
C2228: left of '.setA' must have class/struct/union
C3245: 'Interface::m_AttachedService': use of a variable template requires template argument list

如果能帮助理解正确使用模板,我们将不胜感激!

最佳答案

让我们从一个最小的程序开始,该程序无需执行任何有用的操作即可构建和运行。

#include <string>

class Interface
{
};

class Service
{
protected:
Service() {}
~Service() {}
virtual void init() = 0;
};

class MyService : public Service, public Interface
{
private:
int A;
std::string B;
protected:
Interface x;
public:
MyService() {}
~MyService() {}
void init() {}
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};

int main()
{
MyService myserv;
myserv.init();
}

您会注意到,为了达到该基线,您发布的代码几乎没有变化。

  1. Interface 是空的。
  2. Service 的成员函数在public 部分。 Service 的默认构造函数和析构函数具有空实现。
  3. MyService 的默认构造函数和析构函数位于该类的 public 部分,它们具有空实现。
  4. MyService::init() 有一个空的实现。

现在我们可以开始添加更多代码了。

我将 MyService::init() 更改为:

  void init() { x.init(this); }

没有其他更改,我得到以下编译器错误。

socc.cc: In member function ‘virtual void MyService::init()’:
socc.cc:25:23: error: ‘class Interface’ has no member named ‘init’
void init() { x.init(this);}

现在,Interface 需要使用 init 函数进行更新。

我添加了一个虚拟实现来插入流程向前发展。

class Interface
{
public:
template <class T> bool init(T *_Service) { return true; }
};

是时候向 Interface::init() 添加一些有用的东西了。将其更改为

template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}

产生以下编译器错误,这并不奇怪。

socc.cc: In instantiation of ‘bool Interface::init(T*) [with T = MyService]’:
socc.cc:31:32: required from here
socc.cc:8:23: error: ‘AttachService’ was not declared in this scope
AttachService(*_Service);
~~~~~~~~~~~~~^~~~~~~~~~~

是时候添加 AttachService 了。将 Interface 更改为(关闭匹配你所拥有的)

class Interface
{
public:
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}

template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = *_Service;
}

protected:
template<typename T> static T m_AttachedService;
};

产生以下编译器错误。

socc.cc: In instantiation of ‘void Interface::AttachService(T) [with T = MyService]’:
socc.cc:8:10: required from ‘bool Interface::init(T*) [with T = MyService]’
socc.cc:39:32: required from here
socc.cc:14:33: error: no match for ‘operator*’ (operand type is ‘MyService’)
m_AttachedService<T> = *_Service;
^~~~~~~~~

这是有道理的。在 AttachServie 中,_Service 不是指针。

Inteface::AttachService 更改为:

  template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = _Service;
}

使编译器错误消失,但存在链接器错误。

:socc.cc:(.rdata$.refptr._ZN9Interface17m_AttachedServiceI9MyServiceEE[.refptr._ZN9Interface17m_AttachedServiceI9MyServiceEE]+0x0): undefined reference to `Interface::m_AttachedService<MyService>'
collect2: error: ld returned 1 exit status

这是有道理的,因为我们还没有定义 static 成员变量。

添加以下行

template<typename T> T Interface::m_AttachedService;

Interface 定义之后立即处理链接器错误。

以下是完整程序的下一个版本,它成功构建并运行,尽管它仍然没有做任何有用的事情。

#include <string>

class Interface
{
public:
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}

template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = _Service;
}

protected:
template<typename T> static T m_AttachedService;
};

template<typename T> T Interface::m_AttachedService;

class Service
{
protected:
Service() {}
~Service() {}
virtual void init() = 0;
};

class MyService : public Service, public Interface
{
private:
int A;
std::string B;
protected:
Interface x;
public:
MyService() {}
~MyService() {}
void init() { x.init(this); }
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};

int main()
{
MyService myserv;
myserv.init();
}

是时候将您的 AttachedService 版本添加到 Interface

template <typename T> T AttachedService() { return m_AttachedService; }

这会产生以下编译器错误。

socc.cc: In member function ‘T Interface::AttachedService()’:
socc.cc:17:73: error: missing template arguments before ‘;’ token
template <typename T> T AttachedService() { return m_AttachedService; }

这是有道理的,因为 m_AttachedService 不是成员变量而是成员变量模板。

将其更改为

template <typename T> T AttachedService() { return m_AttachedService<T>; }

删除该错误。


现在是 Interface 中的最后一部分。您发布的嵌套类 InterfaceListener 听起来不错。你有

  class InterfaceListener
{
void Received()
{
int a = 1;
std::string b = "hello";
AttachedService().setA(a);
m_AttachedService.setB(b);
};
};

该类问题:

  1. AttachedService() 是不对的,因为它是一个成员函数模板。您必须提供一个模板参数才能使用它。
  2. 此外,AttachedService() 不是static 成员函数。您需要 Interface 的实例才能进行该调用。
  3. m_AttachedService 不是成员变量。它是一个成员变量模板。您必须提供一个模板参数才能使用它。
  4. setA()setB() 函数仅在模板参数为MyService 时有效。在特定于某个类型的函数中包含代码没有意义。

我会留给您考虑您打算如何使用 InterfaceListener 并适本地定义它的功能。在此之前,我会构建并运行以下程序。

#include <string>

class Interface
{
public:
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}

template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = _Service;
}

template <typename T> T AttachedService() { return m_AttachedService<T>; }

protected:
template<typename T> static T m_AttachedService;

};

template<typename T> T Interface::m_AttachedService;

class Service
{
protected:
Service() {}
~Service() {}
virtual void init() = 0;
};

class MyService : public Service, public Interface
{
private:
int A;
std::string B;
protected:
Interface x;
public:
MyService() {}
~MyService() {}
void init() { x.init(this); }
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};

int main()
{
MyService myserv;
myserv.init();
}

关于c++ - 使用模板函数传递模板参数时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50161454/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com