表达式必须具有类类型

我已经有一段时间没有用 c + + 编写代码了,当我试图编译这个简单的代码片段时,我被卡住了:

class A
{
public:
void f() {}
};


int main()
{
{
A a;
a.f(); // works fine
}


{
A *a = new A();
a.f(); // this doesn't
}
}
320975 次浏览

It's a pointer, so instead try:

a->f();

Basically the operator . (used to access an object's fields and methods) is used on objects and references, so:

A a;
a.f();
A& ref = a;
ref.f();

If you have a pointer type, you have to dereference it first to obtain a reference:

A* ptr = new A();
(*ptr).f();
ptr->f();

The a->b notation is usually just a shorthand for (*a).b.

A note on smart pointers

The operator-> can be overloaded, which is notably used by smart pointers. When you're using smart pointers, then you also use -> to refer to the pointed object:

auto ptr = make_unique<A>();
ptr->f();

Summary: Instead of a.f(); it should be a->f();

In main you have defined a as a pointer to object of A, so you can access functions using the -> operator.

An alternate, but less readable way is (*a).f()

a.f() could have been used to access f(), if a was declared as: A a;

a is a pointer. You need to use->, not .

Allow an analysis.

#include <iostream>   // not #include "iostream"
using namespace std;  // in this case okay, but never do that in header files


class A
{
public:
void f() { cout<<"f()\n"; }
};


int main()
{
/*
// A a; //this works
A *a = new A(); //this doesn't
a.f(); // "f has not been declared"
*/ // below




// system("pause");  <-- Don't do this. It is non-portable code. I guess your
//                       teacher told you this?
//                       Better: In your IDE there is prolly an option somewhere
//                               to not close the terminal/console-window.
//                       If you compile on a CLI, it is not needed at all.
}

As a general advice:

0) Prefer automatic variables
int a;
MyClass myInstance;
std::vector<int> myIntVector;


1) If you need data sharing on big objects down
the call hierarchy, prefer references:


void foo (std::vector<int> const &input) {...}
void bar () {
std::vector<int> something;
...
foo (something);
}




2) If you need data sharing up the call hierarchy, prefer smart-pointers
that automatically manage deletion and reference counting.


3) If you need an array, use std::vector<> instead in most cases.
std::vector<> is ought to be the one default container.


4) I've yet to find a good reason for blank pointers.


-> Hard to get right exception safe


class Foo {
Foo () : a(new int[512]), b(new int[512]) {}
~Foo() {
delete [] b;
delete [] a;
}
};


-> if the second new[] fails, Foo leaks memory, because the
destructor is never called. Avoid this easily by using
one of the standard containers, like std::vector, or
smart-pointers.

As a rule of thumb: If you need to manage memory on your own, there is generally a superiour manager or alternative available already, one that follows the RAII principle.