c++ 使用重载赋值运算符或重载左移运算符获取数据成员的值

z9smfwbn  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(106)

我试图重载赋值运算符和左移运算符,使其返回存储在类中的数据。我正试图使重载赋值操作符和左移操作符作为方便的操作符,用于访问类内部的数据。
我已经能够重载赋值运算符来设置数据,但对于获取数据,我得到了下面的错误。
tempate.h出错

error C2805: binary 'operator <<' has too few parameters
error C2805: binary 'operator =' has too few parameters
error C2447: '{': missing function header (old-style formal list?)
error C2447: '{': missing function header (old-style formal list?)
error C2805: binary 'operator <<' has too few parameters
error C2805: binary 'operator =' has too few parameters
error C2447: '{': missing function header (old-style formal list?)
error C2447: '{': missing function header (old-style formal list?)

字符串
main.cpp中的错误

error C2440: 'initializing': cannot convert from 'SetOnce<int>' to 'int'


错误代码

template<typename T>
inline T SetOnce<T>::operator<<(void) const
{
    return this->get();
}

template<typename T>
inline T SetOnce<T>::operator=(void) const
{
    return this->get();
}


完整代码:
template.h

#pragma once
#include <mutex>
#include <atomic>

class DataNotSetException: public std::exception
{
public:
    static inline const char* message = "Data Not Set before Get Operation";
    const char* what()
    {
        return message;
    }
};

template<typename T>
class SetOnce
{
private:
    T data;
    std::once_flag flag;
    std::atomic_bool data_set{ false };
    void do_once(const T& data);
public:
    T get(void) const;
    void set(const T& data);
    bool is_set(void) const;
    void operator=(const T& data);
    T operator<< (void) const; //Error in this line
    T operator= (void) const; //Error in this line
    SetOnce() {}
};

template<typename T>
inline void SetOnce<T>::do_once(const T& data)
{
    this->data = data;
    this->data_set.store(true);
}

//If data is not been set throw data not set exception (DataNotSetException)
template<typename T>
inline T SetOnce<T>::get(void) const
{
    if (this->is_set() == true)
    {
        return this->data;
    }
    else
    {
        throw DataNotSetException();
    }
}

template<typename T>
inline void SetOnce<T>::set(const T& data)
{
    std::call_once(this->flag, &SetOnce::do_once, this, data);
}

template<typename T>
inline bool SetOnce<T>::is_set(void) const
{
    return this->data_set.load();
}

template<typename T>
inline void SetOnce<T>::operator=(const T& data)
{
    this->set(data);
}

template<typename T>
inline T SetOnce<T>::operator<<(void) const //Error in this line
{
    return this->get();
}

template<typename T>
inline T SetOnce<T>::operator=(void) const //Error in this line
{
    return this->get();
}


main.cpp

int main(void)
{
    SetOnce<int> a1;
    a1 = 175;
    std::cout << a1.get() << std::endl;
    int z1 = a1; //Error in this line
    std::cout << z1 << std::endl;
}

rqcrx0a6

rqcrx0a61#

你的问题其实有两个:1.运算符过载; 2.演员

运算符重载

要重载运算符,您应该了解function overloading and operator overloading是什么。重载应该满足一些基本的函数重载要求,比如运算符的函数签名。
例如,operator=operator<<是二元运算符,这意味着您应该为它们提供两个且仅两个参数。此外,operator=通常返回对象的引用,operator<<通常返回std::ostream对象的引用。
更正后的运算符重载函数如下:

// in class SetOnce
SetOnce<T> &operator=(const T &other);
friend std::ostream& operator<<(std::ostream& os, const SetOnce<T>& obj);

// outside the class
template <typename T> inline SetOnce<T> &SetOnce<T>::operator=(const T &other) {
  // if data has been set, ignore the assignment
  if (!this->data_set) {
    this->set(other);
    this->data_set = true;
  }
  return *this;
}

template<typename T>
std::ostream &operator<<(std::ostream &os, const SetOnce<T> &obj) {
  os << obj.data;
  return os;
}

字符串
这里我提供了两种重载。
1.函数SetOnce<T> &SetOnce<T>::operator=(const T &other)被重载为成员函数。我们只为二元运算符提供一个参数的原因是因为this被隐式地用作第一个函数的参数,这意味着我们不必显式地写出它。
1.函数std::ostream& operator<<(std::ostream& os, const SetOnce<T>& obj)不是SetOnce的成员函数,它被称为 friend function。没有隐式提供this,因此我们提供了两个参数。使用友元函数重载会破坏封装,这一点值得三思。更好的方法是在类外重载operator<<,并且不要将此函数标记为friend,然后在函数中使用SetOnce::get
operator<<通常用于打印,我不建议您使用它来赋值。但是你仍然可以使用它来实现,只要你的函数的签名满足要求。可能的函数签名是SetOnce<T>& operator<<(const T& val),并且使用它的可能方式可以是:

SetOnce<int> s;
int a = 5;
s << a;

Cast运算符

main函数中,有一个脚本:

int z1 = a1; // Assign an object of SetOnce<int> to int


这需要cast operator来处理作业。
因此,您应该在SetOnce中实现此函数:

explicit operator int() const {return this->get();}

代码

template.h:

// template.h
#pragma once
#include <atomic>
#include <mutex>
#include <iostream>

class DataNotSetException : public std::exception {
public:
  static inline const char *message = "Data Not Set before Get Operation";
  const char *what() { return message; }
};

template <typename T> class SetOnce {
private:
  T data;
  std::once_flag flag;
  std::atomic_bool data_set{false};
  void do_once(const T &data);

public:
  T get(void) const;
  void set(const T &data);
  bool is_set(void) const;
  // T operator<<(void) const; // Error in this line
  // T operator=(void) const;  // Error in this line
  SetOnce<T> &operator=(const T &other);
  friend std::ostream& operator<<(std::ostream& os, const SetOnce<T>& obj);
  explicit operator int() const {return this->get();}

  SetOnce() {}
};

template<typename T>
std::ostream &operator<<(std::ostream &os, const SetOnce<T> &obj) {
  os << obj.data;
  return os;
}

template <typename T> inline void SetOnce<T>::do_once(const T &data) {
  this->data = data;
  this->data_set.store(true);
}

// If data is not been set throw data not set exception (DataNotSetException)
template <typename T> inline T SetOnce<T>::get(void) const {
  if (this->is_set() == true) {
    return this->data;
  } else {
    throw DataNotSetException();
  }
}

template <typename T> inline void SetOnce<T>::set(const T &data) {
  std::call_once(this->flag, &SetOnce::do_once, this, data);
}

template <typename T> inline bool SetOnce<T>::is_set(void) const {
  return this->data_set.load();
}

template <typename T> inline SetOnce<T> &SetOnce<T>::operator=(const T &other) {
  // if data has been set, ignore the assignment
  if (!this->data_set) {
    this->set(other);
    this->data_set = true;
  }
  return *this;
}


main.cpp:

// main.cpp

#include "template.h"

#include <iostream>

int main(void) {
  SetOnce<int> a1;
  a1 = 175;
  std::cout << a1.get() << std::endl;
  int z1 = (int)a1;
  std::cout << z1 << std::endl;
}

相关问题