使用 CRTP 使用 std::unique_ptr 向上铸造
up casting with CRTP using std::unique_ptr
我指的是这个并使用CRTP来跟踪正在创建的对象数量。但是当我尝试将Professor
或Student
class
与std::unique_ptr
Person
class
时,我遇到了编译问题。请参考下面的片段,链接在这里
#include <iostream>
#include <vector>
#include <memory>
#include <numeric>
#include <exception>
using namespace std;
template<typename T>
class Person
{
public:
Person(string Name="", int Age=0) : name(Name), age(Age)
{
++cur_id;
}
virtual ~Person() {}
virtual void getdata() = 0;
virtual void putdata() = 0;
protected:
string name;
int age;
static int cur_id;
};
template<typename T> int Person<T>::cur_id = 0;
class Professor : public Person<Professor>
{
public:
Professor(string Name="", int Age=0, int Publications=0);
~Professor() {}
void getdata() override;
void putdata() override;
protected:
bool IsValidInput();
private:
int publications;
};
Professor::Professor(string Name, int Age, int Publications) try : Person(Name,Age), publications(Publications)
{
}
// Catch constructor that fails
catch(std::exception & e)
{
std::cout<<"n Exception - "<<e.what()<<std::endl;
exit(1);
}
bool Professor::IsValidInput()
{
if (name.empty() || (name.length() > 100))
{
return false;
}
if ( age <= 0 || age > 80 )
{
return false;
}
if ( publications <= 0 || publications > 1000)
{
return false;
}
return true;
}
void Professor::getdata()
{
cout<< "Enter Name age publications" << endl;
cin >> name >> age >> publications;
if (!IsValidInput())
{
throw std::invalid_argument("wrong arguments");
}
}
void Professor::putdata()
{
cout << name << " " << age << " " << publications << " " << cur_id << endl;
}
class Student : public Person<Student>
{
public:
Student(string Name="", int Age=0, const vector<int> & Marks = vector<int>());
~Student() {}
void getdata() override;
void putdata() override;
protected:
bool IsValidInput();
private:
vector<int> marks;
static const int TOTAL_MARKS = 5;
};
Student::Student(string Name, int Age, const vector<int> & Marks) try : Person(Name,Age), marks(Marks)
{
}
// Catch constructor that fails
catch(std::exception & e)
{
std::cout<<"n Exception - "<<e.what()<<std::endl;
exit(1);
}
void Student::getdata()
{
int mark = 0;
cout<< "Enter Name age marks(5)" << endl;
cin >> name >> age;
for (size_t idx = 0; idx < TOTAL_MARKS; ++idx)
{
cin >> mark;
marks.push_back(mark);
}
if (!IsValidInput())
{
throw std::invalid_argument("wrong arguments");
}
}
void Student::putdata()
{
cout << name << " " << age << " " << std::accumulate(marks.begin(),marks.end(),0) << " " << cur_id << endl;
}
bool Student::IsValidInput()
{
if (name.empty() || (name.length() > 100))
{
return false;
}
if ( age <= 0 || age > 80 )
{
return false;
}
for (size_t idx = 0; idx < marks.size(); ++idx)
{
if ( marks[idx] < 0 || marks[idx] > 100 )
{
return false;
}
}
return true;
}
int main()
{
int totalObj = 0, type = 0;
cout<< "Enter total obj : ";
cin >> totalObj;
std::vector<std::unique_ptr<Person<int>>> person;
for (int idx = 0; idx < totalObj; ++idx)
{
cout<< "Enter obj type (1 or 2) : ";
cin >> type;
switch(type)
{
case 1:
{
std::unique_ptr<Person<int>> temp(std::make_unique<Professor>());
temp->getdata();
person.push_back(std::move(temp));
}
break;
case 2:
{
std::unique_ptr<Person<int>> temp(std::make_unique<Student>());
temp->getdata();
person.push_back(std::move(temp));
}
break;
default:
break;
}
}
for (auto itr = person.begin(); itr != person.end(); ++itr)
{
(*itr)->putdata();
}
return 0;
}
问题出在switch case 1 and 2
.我只是为了实例化class Person
而使用int
.当我编译它时,我收到以下错误
In function 'int main()':
181:80: error: no matching function for call to 'std::unique_ptr<Person<int> >::unique_ptr(std::_MakeUniq<Professor>::__single_object)'
181:80: note: candidates are:
In file included from /usr/include/c++/4.9/memory:81:0,
from 3:
/usr/include/c++/4.9/bits/unique_ptr.h:228:2: note: template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&)
unique_ptr(auto_ptr<_Up>&& __u) noexcept;
^
/usr/include/c++/4.9/bits/unique_ptr.h:228:2: note: template argument deduction/substitution failed:
181:80: note: 'std::_MakeUniq<Professor>::__single_object {aka std::unique_ptr<Professor, std::default_delete<Professor> >}' is not derived from 'std::auto_ptr<_Up>'
In file included from /usr/include/c++/4.9/memory:81:0,
from 3:
请建议如何将Professor and Student
向上投射到Person std::unique_ptr
。
您的问题是Student
和Professor
没有扩展Person<int>
。事实上,Person<int>
与Professor
无关,每个Person<...>
都是完全不同的阶级,彼此之间没有关系。
如果要在向量中保存所有人员类型,则需要一个在所有Person<...>
上提供接口的多态类。
你的问题的解决方案是创建一个抽象的人:
struct AbstractPerson {
virtual void getdata() = 0;
virtual void putdata() = 0;
virtual ~AbstractPerson() = default;
};
然后,Person<T>
从该类继承:
template<typename T>
struct Person : AbstractPerson {
// ...
};
然后,将该不相关的std::vector<Person<int>>
替换为:
std::vector<std::unique_ptr<AbstractPerson>> person;
// ...
person.emplace_back(std::make_unique<Student>()); // works!
以下是您的工作和稍微现代化的代码的实时版本:Live on Coliru
相关文章:
- 检测使用 CRTP 的类中的成员函数
- 简化使用 CRTP 模式的类的声明
- 使用 CRTP 实现单例
- c++ 使用 CRTP 为变量模板中的每个类型创建纯虚拟重载
- 使用CRTP将基类的子类传递给构造函数
- 如何使用 CRTP 创建少量对象?
- 使用 CRTP 进行选择性静态成员继承
- C++使用 CRTP 模板模板基类中的构造函数
- 如何使用 CRTP 创建具有基类的可选模板参数
- 如何使用 CRTP 自注册类实例?
- 使用CRTP确定生成代码
- 使用 CRTP 使用 std::unique_ptr 向上铸造
- 如何使用CRTP实施来修复强大的封装规则
- 使用CRTP时,如何调用派生类的构造函数
- 在 C++20 中使用 CRTP 派生"using"
- 在这种情况下,我如何使用CRTP删除虚拟方法
- C++中使用CRTP的模板化Singleton策略
- 使用 CRTP 模拟类
- 在 C++11 中使用 CRTP 作为抽象静态方法的替代方法
- 使用CRTP时确保安全