尝试将对象传递给同一个模板类进行复制

Posted

技术标签:

【中文标题】尝试将对象传递给同一个模板类进行复制【英文标题】:Try to pass an object to a same template class to copy 【发布时间】:2020-04-01 15:19:09 【问题描述】:

我实际上是为了理解模板的概念并实现一个简单的模板。我几乎设法编写一个构造函数来复制同一类的实例。

#include <iostream>

// template <typename T>
template <class T>
class vec2 
private:
    static int instance;
    T const x;
    T const y;
public:
    vec2() : x(0), y(0) 
        std::cout << "Default constructor" << std::endl;
        vec2<T>::instance++;
        return;
    

    vec2(T const &x, T const &y) : x(x), y(y) 
        std::cout << "Parametric constructor" << std::endl;
        vec2<T>::instance++;
        return;
    

    vec2(vec2<T> const & src) 
        *this = src;
        std::cout << "Copy constructor" << std::endl;
        vec2<T>::instance++;
        return;
    

    ~vec2()
        std::cout << "Destructor" << std::endl;
        vec2<T>::instance--;
        return;
    

    vec2 & operator=(vec2 const & rhs) 
        this->x = rhs.get_x();
        this->y = rhs.get_y();
        return *this;
    

  // get
    static int get_instance() 
        return vec2<T>::instance;
    

    T get_x() const 
        return this->x;
    

    T get_y() const 
        return this->y;
    
; 

template <class T>
std::ostream & operator<<(std::ostream & out, vec2<T> const & rhs) 
    out << "[ " << rhs.get_x() << ", " << rhs.get_y() << " ]";
    return out;


template <class T>
int vec2<T>::instance = 0;


int main() 
    vec2<float> a;
    vec2<int> b(21, 42);
    vec2<float> c(21.21f, 42.42f);
    vec2<bool> d(true, false);
    vec2<int> e(b);

    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
    std::cout << d << std::endl;
    std::cout << e << std::endl;

    std::cout << "a.get_x(): " << a.get_x() << std::endl;
    std::cout << "a.get_y(): " << a.get_y() << std::endl;

    std::cout << "b.get_x(): " << b.get_x() << std::endl;
    std::cout << "b.get_y(): " << b.get_y() << std::endl;

    std::cout << "c.get_x(): " << c.get_x() << std::endl;
    std::cout << "c.get_y(): " << c.get_y() << std::endl;

    std::cout << "d.get_x(): " << d.get_x() << std::endl;
    std::cout << "d.get_y(): " << d.get_y() << std::endl;

    return (0);

这里是错误消息,但我不是专家阅读它,我不明白我必须在我的代码中更改什么。因此,如果我有任何想法可以帮助 C++ 中的新手,那就太棒了。

clang++  -std=c++11 -Wconversion *.cpp && ./a.out
main.cpp:24:2: error: constructor for 'vec2<int>' must explicitly initialize the
      const member 'x'
        vec2(vec2<T> const & src) 
        ^
main.cpp:72:12: note: in instantiation of member function 'vec2<int>::vec2'
      requested here
        vec2<int> e(b);
                  ^
main.cpp:9:10: note: declared here
        T const x;
                ^
main.cpp:24:2: error: constructor for 'vec2<int>' must explicitly initialize the
      const member 'y'
        vec2(vec2<T> const & src) 
        ^
main.cpp:10:10: note: declared here
        T const y;
                ^
main.cpp:38:11: error: cannot assign to non-static data member 'x' with
      const-qualified type 'const int'
                this->x = rhs.get_x();
                ~~~~~~~ ^
main.cpp:25:9: note: in instantiation of member function 'vec2<int>::operator='
      requested here
                *this = src;
                      ^
main.cpp:72:12: note: in instantiation of member function 'vec2<int>::vec2'
      requested here
        vec2<int> e(b);
                  ^
main.cpp:9:10: note: non-static data member 'x' declared const here
        T const x;
        ~~~~~~~~^
main.cpp:39:11: error: cannot assign to non-static data member 'y' with
      const-qualified type 'const int'
                this->y = rhs.get_y();
                ~~~~~~~ ^
main.cpp:10:10: note: non-static data member 'y' declared const here
        T const y;
        ~~~~~~~~^
4 errors generated.

【问题讨论】:

这与模板无关。如果您声明一个带有const 类成员的常规类,并且您的构造函数无法初始化它,您将得到同样的错误。 “*this = src;”将不起作用。 x 和 y 必须在初始化部分显式构造。有关详细信息,请参阅您的 C++ 书籍。 【参考方案1】:

正如@Sam Varshavchik 在 cmets 中所说,问题在于您没有在复制构造函数中初始化 const 成员。这是正确的实现:

vec2(vec2<T> const & src) : x(src.get_x()), y(src.get_y())  //<-- initialization of const members
    std::cout << "Copy constructor" << std::endl;
    vec2<T>::instance++;
    return;
 

另外,*this = src; 确实感觉各种不对劲。

【讨论】:

【参考方案2】:

这里是我的原始课程代码,我用*this = src 复制了一份,结果效果很好。那么问题是为什么这适用于常规 class 而不是 template ? 另外,我想像普通班级的行为,地址保持不变。 如果类中有很多成员变量,那么初始化所有成员的方法可能会很复杂? main.c

#include "Vec2.hpp"
#include <iostream>

int main() 
    Vec2 a;
    Vec2 b(21,42);
    Vec2 c(a);

    std::cout << a << std::endl;

    std::cout << "c.get_x(): " << c.get_x() << std::endl;
    std::cout << "c.get_y(): " << c.get_y() << std::endl;

    std::cout << "b.get_x(): " << b.get_x() << std::endl;
    std::cout << "b.get_y(): " << b.get_y() << std::endl;

    std::cout << "a.get_x(): " << a.get_x() << std::endl;
    std::cout << "a.get_y(): " << a.get_y() << std::endl;
    a = b;
    std::cout << "a.get_x(): " << a.get_x() << std::endl;
    std::cout << "a.get_y(): " << a.get_y() << std::endl;
    return 0;

Vec2.cpp

#ifndef VEC2_H
# define VEC2_H

#include <iostream>

class Vec2 
public:
    Vec2(); // canonical
    Vec2(float const x, float const y);
    Vec2(Vec2 const &); // canonical
    ~Vec2();    // canonical

    Vec2 & operator=(Vec2 const & rhs);     // canonical

    static int get_instance();

    float get_x() const ;
    float get_y() const ;

private:
    static int instance;
    float x;
    float y;
; 

std::ostream & operator<< (std::ostream & out, Vec2 const & rhs);

#endif

vec2.hpp

#include "Vec2.hpp"
#include <iostream>

Vec2::Vec2() : x(0), y(0) 
    std::cout << "Default constructor" << std::endl;
    Vec2::instance++;
    return;


Vec2::Vec2(float const x, float const y) : x(x), y(y) 
    std::cout << "Parametric constructor" << std::endl;
    Vec2::instance++;
    return;


Vec2::Vec2(Vec2 const & src) 
    *this = src;
    std::cout << "Copy constructor" << std::endl;
    Vec2::instance++;
    return;


Vec2::~Vec2() 
    std::cout << "Destructor" << std::endl;
    Vec2::instance--;
    return;


Vec2 & Vec2::operator=(Vec2 const & rhs) 
    this->x = rhs.get_x();
    this->y = rhs.get_y();
    return *this;


int Vec2::get_instance()
    return Vec2::instance;


float Vec2::get_x() const 
    return this->x;


float Vec2::get_y() const 
    return this->y;


std::ostream & operator<< (std::ostream & out, Vec2 const & rhs) 
    out << "[ " << rhs.get_x() << ", " << rhs.get_y() << " ]";
    return out;



int Vec2::instance = 0;

【讨论】:

问题不在于常规类和模板类。在此实现中,您的xy 成员不是const。让他们const 你会得到同样的错误。此外,*this = src 将调用(默认定义的)复制赋值运算符,这就是它可能起作用的原因,但这不是你应该这样做的原因。 这就是所有这些信息。我使用这种方法是因为在 42 学校的 tutovideo 中,老师使用这种方法,但可能并不是真正的最佳方法。谢谢你的灯。

以上是关于尝试将对象传递给同一个模板类进行复制的主要内容,如果未能解决你的问题,请参考以下文章

将对象传递给另一个类的构造函数

C++ 将对象传递给函数

将对象传递给 UIViewController 的子视图

Vaadin 12将对象传递给JavaScript的函数:不能编码类

在Kotlin中,如果将对象传递给类的新实例,然后更改某些属性,它是否会在原始对象中更改?

显示时将对象传递给模态