C++/CLI type-cast operator - casting

I have two classes: testClass and castClass:
class testClass
{
public:
int field1;
int field2;
testClass(int f1, int f2) : field1(f1), field2(f2) {}
};
ref class castClass
{
int i;
int j;
public:
castClass(int i, int j) : i(i), j(j) {}
explicit static operator testClass (castClass% c)
{
return testClass(c.i, c.j);
}
};
When I try:
castClass cc(1, 2);
testClass i = (testClass)cc;
it compiles fine.
but when I try to cast as:
castClass% c = castClass(1, 2);
testClass j = (testClass)c;
compiler throws the error:
Error 1 error C2440: 'type cast' : cannot convert from
'castClass' to 'testClass'
Why second case is wrong?

Because castClass is a ref class, the normal way to refer to objects of that type is with ^. Try this, it should work for you.
ref class castClass
{
int i;
int j;
public:
castClass(int i, int j) : i(i), j(j) {}
explicit static operator testClass (castClass^ c)
{
return testClass(c->i, c->j);
}
};
castClass^ cc = gcnew castClass(1, 2);
testClass i = (testClass)cc;
castClass^% c = gcnew castClass(1, 2);
testClass j = (testClass)c;

Related

Can you construct after instantiation? Avoiding empty constructor

I have a class which has a member attribute consisting of an object defined elsewhere. In the code below, A contains a public attribute var which is a B:
class B {
public:
int x, y;
std::vector<int> z;
B(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
B var;
A(int i, int j) {
std::vector<int> someVector;
B(i, j, someVector);
}
};
int main() {
A foo(5, 3);
return 0;
}
This (obviously) doesn't compile as var is instantiated upon an instantiation of A, too late for it to be constructed.
The best way I can do something similar is modify some code:
class B {
public:
int x, y;
std::vector<int> z;
B() {}
void setAttributes(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
B var;
A(int i, int j) {
std::vector<int> someVector;
B.setAttributes(i, j, someVector);
}
};
This does compile because attributes are set after instantiation.
But is there a way to remain closer to the first code snippet?
A(int i, int j) : var(i, j, {}) {}
Also, in your code B(i, j, someVector); does not initialize member variable var, and B.setAttributes(i, j, someVector); wouldn't compile at all.
if you cannot define a useful default constructor and don't want the ugly two step initialization, I guess there is no way around a pointer to B. Something like
#include <memory>
class B {
public:
int x, y;
std::vector<int> z;
B(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
std::unique_ptr<B> var;
A() {
std::vector<int> someVector;
var = std::make_unique<B>(5, 2, someVector);
}
};
int main() {
A foo();
return 0;
}
should do the trick.

How to make an object deeply readonly

How can I make a class, which is sometimes readonly, and sometimes writable? One option is with getter/setters and a flag which indicates if the object is read-only, but that is a lot of overhead. I also desire this readonly property to work deeply on the object, making sure that all of the objects it contains are also readonly or writeable. Here's some example code of the desired behavior which I tried but failed to achieve using const.
This question is quite generic, so has probably been asked before, but I wasn't able to find a good solution to this exact problem on stackoverflow.
Example code:
https://ideone.com/4cXyNF
class InnerClass {
public:
InnerClass(int j) : j_(j) {}
int j_;
};
class OuterClass {
public:
OuterClass(int i, InnerClass& c) : i_(i), reference_(c), pointer_(&c) {}
int i_;
InnerClass& reference_;
InnerClass* pointer_;
};
int main() {
InnerClass c(1);
OuterClass readwrite(2, c);
// Desire these 3 operations to work on the writable object
readwrite.i_ = 3;
readwrite.reference_.j_ = 4;
readwrite.pointer_->j_ = 5;
const OuterClass readonly(6, c);
// COMPILER ERROR: error: assignment of member 'OuterClass::i_'
// in read-only object
// readonly.i_ = 7;
// Desire this to be a compiler error, but it isn't
readonly.reference_.j_ = 8;
// Desire this to be a compiler error, but it isn't
readonly.pointer_->j_ = 9;
return 0;
}
If you change your members to functions, you can create const overloads of the methods like this
class InnerClass {
public:
explicit
InnerClass(int j) : j_(j) {}
int& j() { return j_; }
const int& j() const { return j_; }
private:
int j_;
};
class OuterClass {
public:
OuterClass(int i, InnerClass& c) : i_(i), reference_(c), pointer_(&c) {}
int& i() { return i_; }
const int& i() const { return i_; }
InnerClass const& reference() const { return reference_; };
InnerClass & reference() { return reference_; };
InnerClass const* pointer() const { return pointer_; };
InnerClass * pointer() { return pointer_; };
private:
int i_;
InnerClass& reference_;
InnerClass* pointer_;
};
int main() {
InnerClass c(1);
OuterClass readwrite(2, c);
// Desire these 3 operations to work on the writable object
readwrite.i() = 3;
readwrite.reference().j() = 4;
readwrite.pointer()->j() = 5;
const OuterClass readonly(6, c);
// COMPILER ERROR: error: assignment of member 'OuterClass::i_'
// in read-only object
readonly.i_ = 7;
// Desire this to be a compiler error, and it is
readonly.reference().j() = 8;
// Desire this to be a compiler error, and it is
readonly.pointer()->j() = 9;
return 0;
}
Live on Coliru
You can achieve this by using member functions to return the references / pointers const if the object itself is const.
class InnerClass {
public:
InnerClass(int j) : j_(j) {}
int j_;
};
class OuterClass
{
InnerClass& reference_;
public:
OuterClass(int i, InnerClass& c) : i_(i), reference_(c) {}
int i_;
InnerClass & in() { return reference_; }
InnerClass const & in() const { return reference_; }
};
Now neither i_ nor in().j_ is writable in case outer is const:
InnerClass i{ 1 };
OuterClass write(2, i);
write.i_ = 3; // works
write.in().j_ = 3; // works
OuterClass const read(2, i);
read.i_ = 3; // error!
read.in().j_ = 3; // error!
This is a similar solution as some else already posted, but uses a slightly different approach:
class InnerClass {
public:
InnerClass(int j) : j_(j) {}
int j_;
};
template<bool readOnly>
class OuterClass{
public:
OuterClass(int i, InnerClass& c) : i_(i), reference_(c), pointer_(&c) {}
int i_;
typename std::conditional<readOnly,const InnerClass&, InnerClass&>::type reference_;
typename std::conditional<readOnly,const InnerClass* const, InnerClass*>::type pointer_;
};
int main(int argc,char** args){
InnerClass c(1);
OuterClass<true> readonly(12,c);
//readonly.reference_.j_ = 1; //Error "reference_ is read only"
//readonly.pointer_->j_ = 1; //Error "pointer_ is read only"
OuterClass<false> write(12,c);
write.reference_.j_ = 1;
write.pointer_->j_ = 1;
}

Redefinition using Constructor

I cant understand why I have redefinition trying to run this example. Can anyone tell me?
using namespace std;
class Base {
protected: int *value;
public: Base() {
value = new int,
*value = 1;
};
Base(int &n) {
value = new int[n];
}
};
int main() {
int x=2;
Base zm;
Base(x);
system("Pause");
}
Witaj Przemeku Na StackOverflow!
How about this?:
class Base {
protected: int *value;
public:
Base() {
value = new int,
*value = 1;
};
Base(int &n) {
value = new int[n];
};
};
int main()
{
int x;
x = 2;
Base base;
base = Base(x); <--- fix
return 1;
}
Proszę bardziej formatować kod! ;)

How to intitialize const data using constructor

Hi, I've created a class which has three constructors, two integer members & one const int member. So for one constructor I'm using initializer list to assign const int member but I am getting error in other two constructors
Here is my code:
class base
{
public:
base();
base(const int _count);
base(int a ,int b);
~base();
protected:
int m_ia , m_ib;
const int count;
};
base::base()
{
}
base::base(const int _count):count(_count)
{
}
base::base(int a , int b)
{
m_ia = a ;
m_ib = b;
}
base::~base()
{
}
void main()
{
base *obj2 = new base(1000);
getchar();
}
Number of Errors:2
1.'base::count' : must be initialized in constructor base/member initializer list at base()
2.'base::count' : must be initialized in constructor base/member initializer list at base(int a ,int b)
You should probably make sure all your constructors are initializing all member variables, not just the one's being passed in as arguments. I'd rewrite your constructors as
base::base()
: m_ia() // value initializes i.e. sets to 0
, m_ib()
, count()
{
}
base::base(const int _count)
: m_ia()
, m_ib()
,count(_count)
{
}
base::base(int a , int b)
: m_ia(a)
, m_ib(b)
, count()
{
}
And if you have a C++11 compiler that supports delegating constructors, you could create a 4 constructor that takes 3 arguments and have the other constructors delegate to that one.
base::base()
: base(0, 0, 0)
{
}
base::base(const int _count)
: base(0, 0, _count)
{
}
base::base(int a , int b)
: base(a, b, 0)
{
}
base::base(int a , int b, int count)
: m_ia(a)
, m_ib(b)
, count(count)
{
}
The last constructor can be made private if you don't want it to be part of the class interface.
In c++11 you can have
protected:
int m_ia , m_ib;
const int count = 0;
It works in VS 2013.
As per standard C++ and you current code you have to Initialize your const variable in constructor using initialize list so code can be modified as below :
#include"iostream"
using namespace std;
class base
{
public:
base();
base(const int _count);
base(int a ,int b, const int _count);
~base();
protected:
int m_ia , m_ib;
const int count;
};
base::base():count(0)
{
}
base::base(const int _count):count(_count)
{
}
base::base(int a , int b, const int _count):count(0)
{
m_ia = a;
m_ib = b;
}
base::~base()
{
}
int main()
{
base *obj2 = new base(1000);
getchar();
return 0;
}

How to get rid of the ugly record

class c {
private:
int n[10];
public:
c();
~c();
int operator()(int i) { return n[i];};
};
class cc {
private:
public:
c *mass;
cc();
~cc();
c& operator*() const {return *mass;};
};
int somfunc() {
c *c1 = new c();
cc * cc1 = new cc();
(*cc1->mass)(1);
delete c1;
}
I've got a pointer into class cc to class c.
Is there any way to get rid of record like this:
(*cc1->mass)(1);
and write somethink like that:
cc1->mass(1);
is it impossible?
When I saw the tags "c++" and "operator overloading", my mind alarm turns ON.
C++ operator overloading is complex, and some operators like "()" or "->" make it more difficult.
I suggest, before overloading operators, making either a global function or method with the same purpouse, test it works, and later replace it with the operator.
Global friend function example:
class c {
private:
int n[10];
public:
c();
~c();
// int operator()(int i) { return n[i]; }
// there is a friend global function, that when receives a "c" object,
// as a parameter, or declares a "c" object, as a local variable,
// this function, will have access to the "public" members of "c" objects,
// the "thisref" will be removed, when turned into a method
friend int c_subscript(c thisref, int i) ;
};
int c_subscript(c* thisref, int i)
{
return c->n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c_subscript(objC, 3);
// do something with "x"
return 0;
} // int main(...)
Local function ( "method" ) example:
class c {
private:
int n[10];
public:
c();
~c();
// int operator()(int i) { return n[i]; }
int subscript(int i) ;
};
int c::subscript(int i)
{
return this.n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c->subscript(objC, 3);
// do something with "x"
return 0;
} // int main(...)
And, finally use the overloaded operator:
class c {
private:
int n[10];
public:
c();
~c();
int subscript(int i) ;
int operator()(int i) { return this.subscript(i); }
};
int c::subscript(int i)
{
return this.n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c->subscript(3);
// do something with "x"
int x = c(3);
// do something with "x"
return 0;
} // int main(...)
Note that in the final example, I keep the method with a unique identifier.
Cheers.
Could always do this:
class cc {
private:
c *_mass;
public:
c& mass() const {return *_mass;};
};
Now..
cc1->mass()(1);
If mass were an object, not a pointer, you could use the syntax you want:
class cc {
private:
public:
c mass;
cc();
~cc();
const c& operator*() const {return mass;};
};
…
cc1->mass(1);
You can with
(*(*cc1))(1)
because operator() is applied to an object, not a pointer.
You can use
(**cc1)(1);
Or
cc1->mass->operator()(1);